def get_f_pulse_double_sided(self):

        half_CZ_A = wf.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_f=self.fluxlutman.cz_theta_f(),
            f_01_max=self.fluxlutman.cz_freq_01_max(),
            J2=self.fluxlutman.cz_J2(),
            # E_c=self.fluxlutman.cz_E_c(),
            f_interaction=self.fluxlutman.cz_freq_interaction(),
            sampling_rate=self.fluxlutman.sampling_rate(),
            return_unit='f01')
        half_amp_A = self.fluxlutman.detuning_to_amp(
            (self.fluxlutman.cz_freq_01_max() - half_CZ_A) / (2 * np.pi))
        # first half is mapped to positive voltage
        # NOTE: negative part of the flux arc is ignored

        # 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()

        half_CZ_B = wf.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_f=d_theta_f,
            f_01_max=self.fluxlutman.cz_freq_01_max(),
            J2=self.fluxlutman.cz_J2(),
            f_interaction=self.fluxlutman.cz_freq_interaction(),
            sampling_rate=self.fluxlutman.sampling_rate(),
            return_unit='f01')

        half_amp_B = self.fluxlutman.detuning_to_amp(
            (self.fluxlutman.cz_freq_01_max() - half_CZ_B) / (2 * np.pi),
            positive_branch=False)
        # second half is mapped to negative voltage
        # NOTE: negative part of the flux arc is ignored

        # N.B. No amp scaling and offset present
        f_pulse = np.concatenate([half_CZ_A, half_CZ_B])
        amp = np.concatenate([half_amp_A, half_amp_B])
        return f_pulse, amp
示例#2
0
    def acquire_data_point(self, **kw):
        tlist = (np.arange(0, self.fluxlutman.cz_length(),
                           1/self.fluxlutman.sampling_rate()))
        if not self.fluxlutman.czd_double_sided():
            f_pulse = wf.martinis_flux_pulse(
                length=self.fluxlutman.cz_length(),
                lambda_2=self.fluxlutman.cz_lambda_2(),
                lambda_3=self.fluxlutman.cz_lambda_3(),
                theta_f=self.fluxlutman.cz_theta_f(),
                f_01_max=self.fluxlutman.cz_freq_01_max(),
                J2=self.fluxlutman.cz_J2(),
                f_interaction=self.fluxlutman.cz_freq_interaction(),
                sampling_rate=self.fluxlutman.sampling_rate(),
                return_unit='f01')
        else:
            f_pulse = self.get_f_pulse_double_sided()

        # extract base frequency from the Hamiltonian
        w_q0 = np.real(self.H_0[1,1])
        eps_vec = f_pulse - w_q0

        qoi = simulate_quantities_of_interest(
            H_0=self.H_0,
            tlist=tlist, eps_vec=eps_vec,
            sim_step=1e-9, verbose=False)

        cost_func_val = abs(qoi['phi_cond']-180) + qoi['L1']*100 * 5
        return cost_func_val, qoi['phi_cond'], qoi['L1']*100, qoi['L2']*100
    def test_QWG_flux_lutman_basic_wfs_CZ(self):
        """
        Test the basic waveform CZ and CZ with phase correction
        """
        self.QWG_flux_lutman.sampling_rate(1e9)
        self.QWG_flux_lutman.F_amp(0.5)
        self.QWG_flux_lutman.F_length(1e-6)
        self.QWG_flux_lutman.F_compensation_delay(500e-9)
        self.QWG_flux_lutman.Z_amp(0.05)
        corr_len = 10
        self.QWG_flux_lutman.Z_length(corr_len * 1e-9)

        CZ = self.QWG_flux_lutman.standard_waveforms()['adiabatic']
        CZ_expected = wf.martinis_flux_pulse(
            length=self.QWG_flux_lutman.F_length(),
            lambda_2=self.QWG_flux_lutman.F_lambda_2(),
            lambda_3=self.QWG_flux_lutman.F_lambda_3(),
            theta_f=self.QWG_flux_lutman.F_theta_f(),
            f_01_max=self.QWG_flux_lutman.F_f_01_max(),
            J2=self.QWG_flux_lutman.F_J2(),
            E_c=self.QWG_flux_lutman.F_E_c(),
            V_per_phi0=self.QWG_flux_lutman.V_per_phi0(),
            f_interaction=self.QWG_flux_lutman.F_f_interaction(),
            f_bus=None,
            asymmetry=self.QWG_flux_lutman.F_asymmetry(),
            sampling_rate=self.QWG_flux_lutman.sampling_rate(),
            return_unit='V')
        np.testing.assert_array_equal(CZ, CZ_expected)
        CZ_phase_corr = \
            self.QWG_flux_lutman.standard_waveforms()['adiabatic_Z']

        # Test CZ_with_phase_correction
        Z_corr = np.ones(corr_len) * 0.05
        CZ_phase_corr_expected = np.concatenate([CZ, Z_corr])
        np.testing.assert_array_equal(CZ_phase_corr, CZ_phase_corr_expected)
示例#4
0
    def get_f_pulse_double_sided(self):
        half_CZ_A = wf.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_f=self.fluxlutman.cz_theta_f(),
            f_01_max=self.fluxlutman.cz_freq_01_max(),
            J2=self.fluxlutman.cz_J2(),
            # E_c=self.fluxlutman.cz_E_c(),
            f_interaction=self.fluxlutman.cz_freq_interaction(),
            sampling_rate=self.fluxlutman.sampling_rate(),
            return_unit='f01')

        # 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()

        half_CZ_B = wf.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_f=d_theta_f,
            f_01_max=self.fluxlutman.cz_freq_01_max(),
            J2=self.fluxlutman.cz_J2(),
            f_interaction=self.fluxlutman.cz_freq_interaction(),
            sampling_rate=self.fluxlutman.sampling_rate(),
            return_unit='f01')

        # N.B. No amp scaling and offset present
        f_pulse = np.concatenate([half_CZ_A, half_CZ_B])
        return f_pulse
    def standard_waveforms(self):
        '''
        Returns standard waveforms, without delays or distortions applied.
        '''
        # Block pulses
        # Pulse is not IQ modulated, so block_Q is not used.
        block = wf.single_channel_block(self.F_amp(), self.F_length(),
                                        sampling_rate=self.sampling_rate())

        gaussI, gaussQ = wf.gauss_pulse(self.S_amp(), self.S_gauss_sigma(),
                                        nr_sigma=4,
                                        sampling_rate=self.sampling_rate(),
                                        axis='x', phase=0, motzoi=0, delay=0,
                                        subtract_offset='first')

        # New version of fast adiabatic pulse
        martinis_pulse_v2 = wf.martinis_flux_pulse(
            length=self.F_length(),
            lambda_2=self.F_lambda_2(),
            lambda_3=self.F_lambda_3(),
            theta_f=self.F_theta_f(),
            f_01_max=self.F_f_01_max(),
            J2=self.F_J2(),
            E_c=self.F_E_c(),
            V_per_phi0=self.V_per_phi0(),
            V_offset=self.V_offset(),
            f_interaction=self.F_f_interaction(),
            f_bus=None,
            asymmetry=self.F_asymmetry(),
            sampling_rate=self.sampling_rate(),
            return_unit='V')

        # Flux pulse for single qubit phase correction
        z_nr_samples = int(np.round(self.Z_length() * self.sampling_rate()))
        single_qubit_phase_correction = np.ones(z_nr_samples) * self.Z_amp()
        single_qubit_phase_correction_grover = \
            np.ones(z_nr_samples) * self.Z_amp_grover()

        if self.disable_CZ():
            martinis_pulse_v2 *= 0
        # Construct phase corrected pulses
        martinis_phase_corrected = np.concatenate(
            [martinis_pulse_v2, single_qubit_phase_correction])
        martinis_phase_corrected_grover = np.concatenate(
            [martinis_pulse_v2, single_qubit_phase_correction_grover])

        return {'square': block,
                'adiabatic': martinis_pulse_v2,
                'adiabatic_Z': martinis_phase_corrected,
                'adiabatic_Z_grover': martinis_phase_corrected_grover,
                'gauss': gaussI}
示例#6
0
    def chan_wf(self, chan, tvals):
        t = tvals - tvals[0]
        martinis_pulse = martinis_flux_pulse(
            length=self.length,
            lambda_coeffs=self.lambda_coeffs,
            theta_f=self.theta_f,
            g2=self.g2,
            E_c=self.E_c,
            f_bus=self.f_bus,
            f_01_max=self.f_01_max,
            dac_flux_coefficient=self.dac_flux_coefficient,
            return_unit='V')

        # amplitude is not used because of parameterization but
        # we use the sign of the amplitude to set the flux compensation
        return martinis_pulse * np.sign(self.amplitude)
示例#7
0
    def test_simulate_quantities_of_interest(self):
        # Hamiltonian pars
        alpha_q0 = 250e6 * 2 * np.pi
        J = 2.5e6 * 2 * np.pi
        w_q0 = 6e9 * 2 * np.pi
        w_q1 = 7e9 * 2 * np.pi

        H_0 = czu.coupled_transmons_hamiltonian(w_q0,
                                                w_q1,
                                                alpha_q0=alpha_q0,
                                                J=J)
        f_interaction = w_q0 + alpha_q0
        f_01_max = w_q1

        J2 = np.sqrt(2) * J
        length = 180e-9
        sampling_rate = 1e9  #2.4e9
        lambda_2 = 0
        lambda_3 = 0
        V_per_phi0 = 2
        E_c = 250e6

        theta_f = 60

        tlist = (np.arange(0, length, 1 / sampling_rate))
        f_pulse = martinis_flux_pulse(length,
                                      lambda_2=lambda_2,
                                      lambda_3=lambda_3,
                                      theta_f=theta_f,
                                      f_01_max=f_01_max,
                                      E_c=E_c,
                                      V_per_phi0=V_per_phi0,
                                      f_interaction=f_interaction,
                                      J2=J2,
                                      return_unit='f01',
                                      sampling_rate=sampling_rate)
        eps_vec = f_pulse - w_q1

        qoi = czu.simulate_quantities_of_interest(H_0=H_0,
                                                  tlist=tlist,
                                                  eps_vec=eps_vec,
                                                  sim_step=1e-9)
        self.assertAlmostEqual(qoi['phi_cond'], 260.5987691809, places=0)
        self.assertAlmostEqual(qoi['L1'], 0.001272424, places=3)
示例#8
0
    def test_martinis_flux_pulse(self):
        length = 200e-9
        lambda_2 = 0.015
        lambda_3 = 0
        theta_f = 8
        f_01_max = 6.089e9
        J2 = 4.2e6
        E_c = 0
        V_per_phi0 = np.pi / 1.7178
        f_interaction = 4.940e9
        f_bus = None
        asymmetry = 0
        sampling_rate = 1e9
        return_unit = 'V'

        theta_wave = wf.martinis_flux_pulse(length=length,
                                            lambda_2=lambda_2,
                                            lambda_3=lambda_3,
                                            theta_f=theta_f,
                                            f_01_max=f_01_max,
                                            J2=J2,
                                            E_c=E_c,
                                            V_per_phi0=V_per_phi0,
                                            f_interaction=f_interaction,
                                            f_bus=f_bus,
                                            asymmetry=asymmetry,
                                            sampling_rate=sampling_rate,
                                            return_unit=return_unit)

        test_wave = np.array([
            0., 0.03471175, 0.06891321, 0.10213049, 0.13395662, 0.16407213,
            0.19225372, 0.21837228, 0.24238259, 0.26430828, 0.28422502,
            0.30224448, 0.31850026, 0.33313676, 0.34630067, 0.35813509,
            0.36877569, 0.37834846, 0.38696864, 0.39474049, 0.40175751,
            0.40810307, 0.41385119, 0.41906739, 0.42380953, 0.42812868,
            0.43206986, 0.43567281, 0.43897257, 0.44200007, 0.44478268,
            0.4473446, 0.44970728, 0.45188975, 0.45390895, 0.45577993,
            0.45751613, 0.45912955, 0.46063093, 0.46202989, 0.46333506,
            0.46455423, 0.46569439, 0.46676186, 0.46776234, 0.468701,
            0.46958252, 0.47041115, 0.47119076, 0.47192487, 0.47261668,
            0.47326913, 0.4738849, 0.47446644, 0.47501598, 0.47553561,
            0.47602721, 0.47649252, 0.47693314, 0.47735057, 0.47774615,
            0.47812115, 0.47847674, 0.47881399, 0.47913389, 0.47943738,
            0.4797253, 0.47999845, 0.48025757, 0.48050334, 0.4807364,
            0.48095734, 0.48116671, 0.48136502, 0.48155275, 0.48173034,
            0.48189819, 0.4820567, 0.48220622, 0.48234707, 0.48247957,
            0.48260399, 0.48272061, 0.48282967, 0.48293139, 0.48302598,
            0.48311363, 0.48319452, 0.4832688, 0.48333663, 0.48339813,
            0.48345343, 0.48350263, 0.48354583, 0.4835831, 0.48361452,
            0.48364015, 0.48366003, 0.48367421, 0.4836827, 0.48368553,
            0.4836827, 0.48367421, 0.48366003, 0.48364015, 0.48361452,
            0.4835831, 0.48354583, 0.48350263, 0.48345343, 0.48339813,
            0.48333663, 0.4832688, 0.48319452, 0.48311363, 0.48302598,
            0.48293139, 0.48282967, 0.48272061, 0.48260399, 0.48247957,
            0.48234707, 0.48220622, 0.4820567, 0.48189819, 0.48173034,
            0.48155275, 0.48136502, 0.48116671, 0.48095734, 0.4807364,
            0.48050334, 0.48025757, 0.47999845, 0.4797253, 0.47943738,
            0.47913389, 0.47881399, 0.47847674, 0.47812115, 0.47774615,
            0.47735057, 0.47693314, 0.47649252, 0.47602721, 0.47553561,
            0.47501598, 0.47446644, 0.4738849, 0.47326913, 0.47261668,
            0.47192487, 0.47119076, 0.47041115, 0.46958252, 0.468701,
            0.46776234, 0.46676186, 0.46569439, 0.46455423, 0.46333506,
            0.46202989, 0.46063093, 0.45912955, 0.45751613, 0.45577993,
            0.45390895, 0.45188975, 0.44970728, 0.4473446, 0.44478268,
            0.44200007, 0.43897257, 0.43567281, 0.43206986, 0.42812868,
            0.42380953, 0.41906739, 0.41385119, 0.40810307, 0.40175751,
            0.39474049, 0.38696864, 0.37834846, 0.36877569, 0.35813509,
            0.34630067, 0.33313676, 0.31850026, 0.30224448, 0.28422502,
            0.26430828, 0.24238259, 0.21837228, 0.19225372, 0.16407213,
            0.13395662, 0.10213049, 0.06891321, 0.03471175
        ])

        # FIXME:  Only testing for the shape as the waveform has been updated
        self.assertEqual(np.shape(theta_wave), np.shape(test_wave))
        # np.testing.assert_almost_equal(theta_wave, test_wave)

        lambda_2 = -0.02
        # FIXME: we should test if the right warning is raised.
        # with warnings.catch_warnings(record=True) as w:
        theta_wave = wf.martinis_flux_pulse(length=length,
                                            lambda_2=lambda_2,
                                            lambda_3=lambda_3,
                                            theta_f=theta_f,
                                            f_01_max=f_01_max,
                                            J2=J2,
                                            E_c=E_c,
                                            V_per_phi0=V_per_phi0,
                                            f_interaction=f_interaction,
                                            f_bus=f_bus,
                                            asymmetry=asymmetry,
                                            sampling_rate=sampling_rate,
                                            return_unit=return_unit)

        test_wave_2 = np.array([
            0., 0.03234928, 0.06428708, 0.09542742, 0.12543163, 0.1540241,
            0.18100034, 0.20622772, 0.22964031, 0.25122954, 0.2710329,
            0.28912228, 0.30559317, 0.32055543, 0.33412579, 0.34642229,
            0.35756021, 0.3676494, 0.37679261, 0.38508466, 0.39261214,
            0.3994535, 0.40567941, 0.41135325, 0.41653169, 0.42126526,
            0.42559899, 0.42957296, 0.43322283, 0.43658032, 0.43967369,
            0.44252809, 0.44516595, 0.44760729, 0.44987001, 0.45197009,
            0.45392188, 0.45573822, 0.45743067, 0.45900961, 0.4604844,
            0.46186349, 0.46315449, 0.46436431, 0.4654992, 0.46656483,
            0.46756635, 0.46850846, 0.46939543, 0.47023115, 0.47101919,
            0.47176279, 0.47246495, 0.47312839, 0.47375563, 0.47434897,
            0.47491052, 0.47544225, 0.47594595, 0.47642329, 0.47687579,
            0.47730487, 0.47771185, 0.47809794, 0.47846427, 0.47881187,
            0.47914172, 0.47945471, 0.47975169, 0.48003341, 0.48030062,
            0.48055396, 0.48079408, 0.48102155, 0.4812369, 0.48144065,
            0.48163325, 0.48181516, 0.48198676, 0.48214843, 0.48230053,
            0.48244338, 0.48257727, 0.48270249, 0.4828193, 0.48292792,
            0.48302858, 0.48312148, 0.4832068, 0.48328471, 0.48335536,
            0.48341888, 0.4834754, 0.48352503, 0.48356785, 0.48360394,
            0.48363339, 0.48365623, 0.48367252, 0.48368228, 0.48368553,
            0.48368228, 0.48367252, 0.48365623, 0.48363339, 0.48360394,
            0.48356785, 0.48352503, 0.4834754, 0.48341888, 0.48335536,
            0.48328471, 0.4832068, 0.48312148, 0.48302858, 0.48292792,
            0.4828193, 0.48270249, 0.48257727, 0.48244338, 0.48230053,
            0.48214843, 0.48198676, 0.48181516, 0.48163325, 0.48144065,
            0.4812369, 0.48102155, 0.48079408, 0.48055396, 0.48030062,
            0.48003341, 0.47975169, 0.47945471, 0.47914172, 0.47881187,
            0.47846427, 0.47809794, 0.47771185, 0.47730487, 0.47687579,
            0.47642329, 0.47594595, 0.47544225, 0.47491052, 0.47434897,
            0.47375563, 0.47312839, 0.47246495, 0.47176279, 0.47101919,
            0.47023115, 0.46939543, 0.46850846, 0.46756635, 0.46656483,
            0.4654992, 0.46436431, 0.46315449, 0.46186349, 0.4604844,
            0.45900961, 0.45743067, 0.45573822, 0.45392188, 0.45197009,
            0.44987001, 0.44760729, 0.44516595, 0.44252809, 0.43967369,
            0.43658032, 0.43322283, 0.42957296, 0.42559899, 0.42126526,
            0.41653169, 0.41135325, 0.40567941, 0.3994535, 0.39261214,
            0.38508466, 0.37679261, 0.3676494, 0.35756021, 0.34642229,
            0.33412579, 0.32055543, 0.30559317, 0.28912228, 0.2710329,
            0.25122954, 0.22964031, 0.20622772, 0.18100034, 0.1540241,
            0.12543163, 0.09542742, 0.06428708, 0.03234928
        ])

        # FIXME:  Only testing for the shape as the waveform has been updated
        self.assertEqual(np.shape(theta_wave), np.shape(test_wave_2))
示例#9
0
    def acquire_data_point(self, **kw):
        tlist = (np.arange(0, self.fluxlutman.cz_length(),
                           1 / self.fluxlutman.sampling_rate()))
        if not self.fluxlutman.czd_double_sided():
            f_pulse = wf.martinis_flux_pulse(
                length=self.fluxlutman.cz_length(),
                lambda_2=self.fluxlutman.cz_lambda_2(),
                lambda_3=self.fluxlutman.cz_lambda_3(),
                theta_f=self.fluxlutman.cz_theta_f(),
                f_01_max=self.fluxlutman.cz_freq_01_max(),
                J2=self.fluxlutman.cz_J2(),
                f_interaction=self.fluxlutman.cz_freq_interaction(),
                sampling_rate=self.fluxlutman.sampling_rate(),
                return_unit='f01')
        else:
            f_pulse = self.get_f_pulse_double_sided()

        # extract base frequency from the Hamiltonian
        w_q0 = np.real(self.H_0[1, 1])
        eps_vec = f_pulse - w_q0

        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_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

        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(
                (w_q0 / 2) * np.sqrt(1 - (omega / w_q0)**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)
            omega_prime_min = omega_prime(w_min)

            f_pulse = np.clip(f_pulse, 0, w_q0)
            f_pulse_prime = omega_prime(f_pulse)
            Tphi01_q0_vec = Tphi01_q0_sweetspot - f_pulse_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_interpolating(T1_q0, T1_q1, Tphi01_q0_vec, Tphi01_q1)
        else:  # mode where the collapse operators are time-independent, and possibly are 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)

        qoi = simulate_quantities_of_interest_superoperator(
            H_0=self.H_0,
            tlist=tlist,
            c_ops=c_ops,
            eps_vec=eps_vec,
            sim_step=1 / self.fluxlutman.sampling_rate(),
            verbose=False)

        cost_func_val = -np.log10(
            1 -
            qoi['avgatefid_compsubspace_pc'])  # new cost function: infidelity
        #np.abs(qoi['phi_cond']-180) + qoi['L1']*100 * 5
        return cost_func_val, qoi[
            'phi_cond'], qoi['L1'] * 100, qoi['L2'] * 100, qoi[
                'avgatefid_pc'] * 100, qoi['avgatefid_compsubspace_pc'] * 100
    def acquire_data_point(self, **kw):
        tlist = (np.arange(0, self.fluxlutman.cz_length(),
                           1 / self.fluxlutman.sampling_rate()))

        if not self.fluxlutman.czd_double_sided():
            theta_i = np.arctan(2 * self.fluxlutman.cz_J2() /
                                (self.fluxlutman.cz_freq_01_max() -
                                 self.fluxlutman.cz_freq_interaction()))
            theta_f = fix_theta_f(self.fluxlutman.cz_lambda_3(), theta_i)

            f_pulse = wf.martinis_flux_pulse(
                length=self.fluxlutman.cz_length(),
                lambda_2=self.fluxlutman.cz_lambda_2(),
                lambda_3=self.fluxlutman.cz_lambda_3(),
                theta_f=theta_f,  #self.fluxlutman.cz_theta_f(),
                f_01_max=self.fluxlutman.cz_freq_01_max(),
                J2=self.fluxlutman.cz_J2(),
                f_interaction=self.fluxlutman.cz_freq_interaction(),
                sampling_rate=self.fluxlutman.sampling_rate(),
                return_unit='f01')  # return in terms of omega

            #amp = self.fluxlutman.detuning_to_amp((self.fluxlutman.cz_freq_01_max() - f_pulse)/(2*np.pi))
            # transform detuning frequency to (positive) amplitude

        else:
            f_pulse, amp = self.get_f_pulse_double_sided()

        sim_step = 1 / self.fluxlutman.sampling_rate()

        # extract base frequency from the Hamiltonian
        w_q0 = np.real(self.H_0[1, 1])
        w_q1 = np.real(self.H_0[3, 3])
        alpha_q0 = np.real(self.H_0[2, 2]) - 2 * w_q0

        eps_vec = f_pulse - w_q0
        detuning = -eps_vec / (2 * np.pi
                               )  # we express detuning in terms of frequency

        Vo = 1 / np.arccos(((w_q1 - 2 * alpha_q0) / (w_q0 - alpha_q0))**2)
        amp = Vo * np.arccos(((f_pulse - alpha_q0) / (w_q0 - alpha_q0))**2)
        # transformations used to match with Leo's simulations
        # we scale the amplitude and then recompute the pulse in detuning
        amp = amp * self.noise_parameters_CZ.voltage_scaling_factor()
        eps_vec_convolved_new = (w_q0 - 0 * alpha_q0) * np.sqrt(
            np.cos(amp / Vo)) + 0 * alpha_q0 - w_q0
        f_pulse_convolved_new = eps_vec_convolved_new + w_q0
        '''J_new=list()
        for eps in eps_vec:
        	H=hamiltonian_timedependent(self.H_0,eps)
        	J_new.append(np.real(H[1,3]))
        plot(x_plot_vec=[tlist*1e9],
            	  y_plot_vec=[np.array(J_new)/(2*np.pi)/1e6],
            	  title='Coupling during pulse',
                  xlabel='Time (ns)',ylabel='J (MHz)',legend_labels=['J(t)'])'''
        '''    ####### functions that were used to convert from detuning to voltage but now we use 
                       functions from fluxlutman which are the same as those used in the experiment
        def invert_parabola(polynomial_coefficients,y):    # useless
        	a=polynomial_coefficients[0]
        	b=polynomial_coefficients[1]
        	c=polynomial_coefficients[2]
        	return (-b+np.sqrt(b**2-4*a*(c-y)))/(2*a)

        voltage_frompoly = invert_parabola(self.fluxlutman.polycoeffs_freq_conv(),detuning)

        voltage_frompoly_interp = interp1d(tlist,voltage_frompoly)

        voltage_frompoly_convol = voltage_frompoly_interp(tlist_convol1)

        convolved_voltage=scipy.signal.convolve(voltage_frompoly_convol,impulse_response_convol)/sum(impulse_response_convol)
        
        convolved_detuning=give_parabola(self.fluxlutman.polycoeffs_freq_conv(),convolved_voltage)

        eps_vec_convolved=-convolved_detuning*(2*np.pi)
        eps_vec_convolved=eps_vec_convolved[0:np.size(tlist_convol1)]
        f_pulse_convolved=eps_vec_convolved+w_q0
        
        '''

        if self.noise_parameters_CZ.distortions():
            impulse_response = np.gradient(self.fitted_stepresponse_ty[1])

            # plot(x_plot_vec=[self.fitted_stepresponse_ty[0]],y_plot_vec=[self.fitted_stepresponse_ty[1]],
            # 	  title='Step response',
            #       xlabel='Time (ns)')
            # plot(x_plot_vec=[self.fitted_stepresponse_ty[0]],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, amp)
            impulse_response_interp = interp1d(self.fitted_stepresponse_ty[0],
                                               impulse_response)

            tlist_convol1 = tlist
            tlist_convol2 = np.arange(0, self.fluxlutman.cz_length(),
                                      1 / self.fluxlutman.sampling_rate())
            amp_convol = amp_interp(tlist_convol1)
            impulse_response_convol = impulse_response_interp(tlist_convol2)

            # plot(x_plot_vec=[tlist_convol1*1e9],y_plot_vec=[amp_convol],
            # 	  title='Pulse in voltage, length=240ns',
            #       xlabel='Time (ns)',ylabel='Amplitude (V)')
            # plot(x_plot_vec=[tlist_convol*1e9],y_plot_vec=[impulse_response_convol],
            # 	  title='Impulse response',
            #       xlabel='Time (ns)')

            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*1e9],
            # 	  y_plot_vec=[amp_convol, convolved_amp],
            # 	  title='Net-zero, Pulse_length=240ns',
            #       xlabel='Time (ns)',ylabel='Amplitude (V)',legend_labels=['Ideal','Distorted'])

            def give_parabola(polynomial_coefficients, x):
                a = polynomial_coefficients[0]
                b = polynomial_coefficients[1]
                c = polynomial_coefficients[2]
                return a * x**2 + b * x + c

            convolved_detuning_new = give_parabola(
                self.fluxlutman.polycoeffs_freq_conv(), convolved_amp)

            # plot(x_plot_vec=[tlist*1e9,np.arange(np.size(convolved_amp))*sim_step*1e9],
            # 	  y_plot_vec=[detuning/1e9, convolved_detuning_new/1e9],
            # 	  title='Net-zero, Pulse_length=240ns',
            #       xlabel='Time (ns)',ylabel='Detuning (GHz)',legend_labels=['Ideal','Distorted'])

            eps_vec_convolved_new = -convolved_detuning_new * (2 * np.pi)
            eps_vec_convolved_new = eps_vec_convolved_new[0:np.
                                                          size(tlist_convol1)]
            f_pulse_convolved_new = eps_vec_convolved_new + w_q0
        # else:
        # 	eps_vec_convolved_new=eps_vec
        # 	f_pulse_convolved_new=f_pulse

        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_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

        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(
                (w_q0 / 2) * np.sqrt(1 - (omega / w_q0)**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, w_q0)
            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_interpolating(T1_q0, T1_q1, Tphi01_q0_vec, Tphi01_q1)
        else:  # mode where the collapse operators are time-independent, and possibly are 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)

        qoi = simulate_quantities_of_interest_superoperator(
            H_0=self.H_0,
            tlist=tlist,
            c_ops=c_ops,
            eps_vec=eps_vec_convolved_new,
            sim_step=1 / self.fluxlutman.sampling_rate(),
            verbose=False)

        cost_func_val = np.abs(qoi['phi_cond'] -
                               180)  # new cost function: infidelity
        #np.abs(qoi['phi_cond']-180) + qoi['L1']*100 * 5
        return cost_func_val, qoi[
            'phi_cond'], qoi['L1'] * 100, qoi['L2'] * 100, qoi[
                'avgatefid_pc'] * 100, qoi['avgatefid_compsubspace_pc'] * 100
示例#11
0
    def _gen_cz(self):

        dac_scale_factor = self.get_amp_to_dac_val_scale_factor()

        if not self.czd_double_sided():
            CZ = wf.martinis_flux_pulse(
                length=self.cz_length(),
                lambda_2=self.cz_lambda_2(),
                lambda_3=self.cz_lambda_3(),
                theta_f=self.cz_theta_f(),
                f_01_max=self.cz_freq_01_max(),
                J2=self.cz_J2(),
                f_interaction=self.cz_freq_interaction(),
                sampling_rate=self.sampling_rate(),
                return_unit='f01')
            return dac_scale_factor*self.detuning_to_amp(
                self.cz_freq_01_max() - CZ)
        else:
            # Simple double sided CZ pulse implemented in most basic form.
            # repeats the same CZ gate twice and sticks it together.
            half_CZ_A = wf.martinis_flux_pulse(
                length=self.cz_length()*self.czd_length_ratio(),
                lambda_2=self.cz_lambda_2(),
                lambda_3=self.cz_lambda_3(),
                theta_f=self.cz_theta_f(),
                f_01_max=self.cz_freq_01_max(),
                # V_per_phi0=self.cz_V_per_phi0(),
                J2=self.cz_J2(),
                # E_c=self.cz_E_c(),
                f_interaction=self.cz_freq_interaction(),
                sampling_rate=self.sampling_rate(),
                return_unit='f01')
            half_CZ_A = dac_scale_factor*self.detuning_to_amp(
                self.cz_freq_01_max() - half_CZ_A)

            # Generate the second CZ pulse. If the params are np.nan, default
            # to the main parameter
            if not np.isnan(self.czd_theta_f()):
                d_theta_f = self.czd_theta_f()
            else:
                d_theta_f = self.cz_theta_f()

            if not np.isnan(self.czd_lambda_2()):
                d_lambda_2 = self.czd_lambda_2()
            else:
                d_lambda_2 = self.cz_lambda_2()
            if not np.isnan(self.czd_lambda_3()):
                d_lambda_3 = self.czd_lambda_3()
            else:
                d_lambda_3 = self.cz_lambda_3()

            half_CZ_B = wf.martinis_flux_pulse(
                length=self.cz_length()*(1-self.czd_length_ratio()),
                lambda_2=d_lambda_2,
                lambda_3=d_lambda_3,
                theta_f=d_theta_f,
                f_01_max=self.cz_freq_01_max(),
                # V_per_phi0=self.cz_V_per_phi0(),
                J2=self.cz_J2(),
                # E_c=self.cz_E_c(),
                f_interaction=self.cz_freq_interaction(),
                sampling_rate=self.sampling_rate(),
                return_unit='f01')
            half_CZ_B = dac_scale_factor*self.detuning_to_amp(
                self.cz_freq_01_max() - half_CZ_B, positive_branch=False)

            amp_rat = self.czd_amp_ratio()
            waveform = np.concatenate(
                [half_CZ_A, amp_rat*half_CZ_B + self.czd_amp_offset()])

            return waveform
    def acquire_data_point(self, **kw):
        '''# BENCHMARK FOR HOW THE COUPLING IMPACTS THE HAMILTONIAN PARAMETERS
        eigs,eigvectors = self.H_0.eigenstates()
        eigs=eigs/(2*np.pi)
        print('omegaA =',eigs[1])
        print('omegaB =',eigs[2])
        print(eigs[4]-eigs[1]-eigs[2])
        print('etaA =',eigs[3]-2*eigs[1])
        print('etaB =',eigs[5]-2*eigs[2])
        print(eigvectors[4],'\n fidelity with 1 /otimes 1=',np.abs(eigvectors[4].dag().overlap(qtp.basis(9,4)))**2)
        print(eigvectors[5],'\n fidelity with 0 /otimes 2=',np.abs(eigvectors[5].dag().overlap(qtp.basis(9,2)))**2)
        '''

        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))

        #theta_i = np.arctan(2*self.fluxlutman.cz_J2() / (self.fluxlutman.cz_freq_01_max() - self.fluxlutman.cz_freq_interaction()))
        #theta_f=fix_theta_f(self.fluxlutman.cz_lambda_3(),theta_i)
        #theta_i=theta_i*360/(2*np.pi)
        #self.fluxlutman.cz_theta_f(theta_f)

        if not self.fluxlutman.czd_double_sided():
            f_pulse = wf.martinis_flux_pulse(
                length=self.fluxlutman.cz_length(),
                lambda_2=self.fluxlutman.cz_lambda_2(),
                lambda_3=self.fluxlutman.cz_lambda_3(),
                theta_f=self.fluxlutman.cz_theta_f(),
                f_01_max=self.fluxlutman.cz_freq_01_max(),
                J2=self.fluxlutman.cz_J2(),
                f_interaction=self.fluxlutman.cz_freq_interaction(),
                sampling_rate=self.fluxlutman.sampling_rate(),
                return_unit='f01')  # return in terms of omega
            amp = self.fluxlutman.detuning_to_amp(
                (self.fluxlutman.cz_freq_01_max() - f_pulse) / (2 * np.pi))
            # transform detuning frequency to (positive) amplitude
        else:
            f_pulse, amp = self.get_f_pulse_double_sided()

        # For better accuracy in simulations, redefine f_pulse and amp in trems 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/(2*np.pi)/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()

        # extract base frequency from the Hamiltonian
        w_q0 = np.real(self.H_0[1, 1])
        #w_q1=np.real(self.H_0[3,3])
        #alpha_q0=np.real(self.H_0[2,2])-2*w_q0

        #eps_vec = f_pulse - w_q0
        #detuning = -eps_vec/(2*np.pi)     # we express detuning in terms of frequency
        '''#BENCHMARK TO CHECK HOW THE COUPLING VARIES AS A FUNCTION OF DETUNING
        J_new=list()
        for eps in eps_vec:
        	H=hamiltonian_timedependent(self.H_0,eps)
        	J_new.append(np.real(H[1,3]))
        plot(x_plot_vec=[tlist_new*1e9],
            	  y_plot_vec=[np.array(J_new)/(2*np.pi)/1e6],
            	  title='Coupling during pulse',
                  xlabel='Time (ns)',ylabel='J (MHz)',legend_labels=['J(t)'])'''
        '''   USELESS   ####### functions that were used to convert from detuning to voltage but now we use 
                       functions from fluxlutman which are the same as those used in the experiment
        def invert_parabola(polynomial_coefficients,y):    # useless
        	a=polynomial_coefficients[0]
        	b=polynomial_coefficients[1]
        	c=polynomial_coefficients[2]
        	return (-b+np.sqrt(b**2-4*a*(c-y)))/(2*a)

        voltage_frompoly = invert_parabola(self.fluxlutman.polycoeffs_freq_conv(),detuning)

        voltage_frompoly_interp = interp1d(tlist,voltage_frompoly)

        voltage_frompoly_convol = voltage_frompoly_interp(tlist_convol1)

        convolved_voltage=scipy.signal.convolve(voltage_frompoly_convol,impulse_response_convol)/sum(impulse_response_convol)
        
        convolved_detuning=give_parabola(self.fluxlutman.polycoeffs_freq_conv(),convolved_voltage)

        eps_vec_convolved=-convolved_detuning*(2*np.pi)
        eps_vec_convolved=eps_vec_convolved[0:np.size(tlist_convol1)]
        f_pulse_convolved=eps_vec_convolved+w_q0
        
        '''
        def give_parabola(polynomial_coefficients, x):
            a = polynomial_coefficients[0]
            b = polynomial_coefficients[1]
            c = polynomial_coefficients[2]
            return a * x**2 + b * x + c

        if self.noise_parameters_CZ.distortions():
            impulse_response = np.gradient(self.fitted_stepresponse_ty[1])

            # plot(x_plot_vec=[self.fitted_stepresponse_ty[0]],y_plot_vec=[self.fitted_stepresponse_ty[1]],
            # 	  title='Step response',
            #       xlabel='Time (ns)')
            # plot(x_plot_vec=[self.fitted_stepresponse_ty[0]],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)  # amp is now managed already above
            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)

            # plot(x_plot_vec=[tlist_convol1*1e9],y_plot_vec=[amp_convol],
            # 	  title='Pulse in voltage, length=240ns',
            #       xlabel='Time (ns)',ylabel='Amplitude (V)')
            # plot(x_plot_vec=[tlist_convol*1e9],y_plot_vec=[impulse_response_convol],
            # 	  title='Impulse response',
            #       xlabel='Time (ns)')

            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*1e9],
            # 	  y_plot_vec=[amp_convol, convolved_amp],
            # 	  title='Net-zero, Pulse_length=240ns',
            #       xlabel='Time (ns)',ylabel='Amplitude (V)',legend_labels=['Ideal','Distorted'])

            convolved_detuning_new = give_parabola(
                self.fluxlutman.polycoeffs_freq_conv(), convolved_amp)

            # plot(x_plot_vec=[tlist*1e9,np.arange(np.size(convolved_amp))*sim_step*1e9],
            # 	  y_plot_vec=[detuning/1e9, convolved_detuning_new/1e9],
            # 	  title='Net-zero, Pulse_length=240ns',
            #       xlabel='Time (ns)',ylabel='Detuning (GHz)',legend_labels=['Ideal','Distorted'])

            eps_vec_convolved_new = -convolved_detuning_new * (2 * np.pi)
            eps_vec_convolved_new = eps_vec_convolved_new[0:np.
                                                          size(tlist_convol1)]
            f_pulse_convolved_new = eps_vec_convolved_new + w_q0
        else:
            detuning_new = give_parabola(
                self.fluxlutman.polycoeffs_freq_conv(), amp)
            eps_vec_convolved_new = -detuning_new * (2 * np.pi)
            f_pulse_convolved_new = eps_vec_convolved_new + w_q0

        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:

            def expT2(x, gc, amp, tau):
                return gc + gc * amp * np.exp(-x / tau)

            T2_q0_vec = expT2(f_pulse_convolved_new / (2 * np.pi),
                              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_interpolating(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(
                    (w_q0 / 2) * np.sqrt(1 - (omega / w_q0)**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, w_q0)
                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_interpolating(T1_q0, T1_q1, Tphi01_q0_vec,
                                            Tphi01_q1)
            else:  # mode where the collapse operators are time-independent, and possibly are 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)

        qoi = simulate_quantities_of_interest_superoperator(
            H_0=self.H_0,
            tlist=tlist_new,
            c_ops=c_ops,
            w_bus=self.noise_parameters_CZ.w_bus(),
            eps_vec=eps_vec_convolved_new,
            sim_step=sim_step_new,
            verbose=False)

        cost_func_val = -np.log10(
            1 -
            qoi['avgatefid_compsubspace_pc'])  # new cost function: infidelity
        #np.abs(qoi['phi_cond']-180) + qoi['L1']*100 * 5
        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']
def simulate_CZ_trajectory(length,
                           lambda_2,
                           lambda_3,
                           theta_f,
                           f_01_max,
                           f_interaction,
                           J2,
                           E_c,
                           V_per_phi0=1,
                           dac_flux_coefficient=None,
                           asymmetry=0,
                           sampling_rate=2e9,
                           return_all=False,
                           verbose=False):
    """
    Input args:
        length               (float) :parameter for waveform (s)
        lambda_2             (float): parameter for waveform
        lambda_3             (float): parameter for waveform
        theta_f              (float): parameter for waveform (deg)
        f_01_max             (float): parameter for waveform (Hz)
        f_interaction        (float): parameter for waveform (Hz)
        J2                   (float): parameter for waveform (Hz)
        E_c                  (float): parameter for waveform (Hz)
        V_per_phi0           (float): parameter for waveform (V)
        asymmetry            (float): parameter for waveform
        sampling_rate        (float): sampling rate used in simulation (Hz)
        verbose              (bool) : enables optional print statements
        return_all           (bool) : if True returns internal params of the
                                      simulation (see below).
    Returns:
        picked_up_phase in degree
        leakage         population leaked to the 02 state
    N.B. the function only returns the quantities below if return_all is True
        res1:           vector of qutip results for 1 excitation
        res2:           vector of qutip results for 1 excitation
        eps_vec :       vector of detunings as function of time
        tlist:          vector of times used in the simulation
    """
    if dac_flux_coefficient is not None:
        logging.warning('dac_flux_coefficient deprecated. Please use the '
                        'physically meaningful V_per_phi0 instead.')
        V_per_phi0 = np.pi / dac_flux_coefficient

    Hx = qtp.sigmax() * 2 * np.pi  # so that freqs are real and not radial
    Hz = qtp.sigmaz() * 2 * np.pi  # so that freqs are real and not radial

    def J1_t(t, args=None):
        # if there is only one excitation, there is no interaction
        return 0

    def J2_t(t, args=None):
        return J2

    tlist = (np.arange(0, length, 1 / sampling_rate))

    f_pulse = martinis_flux_pulse(length,
                                  lambda_2=lambda_2,
                                  lambda_3=lambda_3,
                                  theta_f=theta_f,
                                  f_01_max=f_01_max,
                                  E_c=E_c,
                                  V_per_phi0=V_per_phi0,
                                  f_interaction=f_interaction,
                                  J2=J2,
                                  return_unit='eps',
                                  sampling_rate=sampling_rate)

    eps_vec = f_pulse

    # function used for qutip simulation
    def eps_t(t, args=None):
        idx = np.argmin(abs(tlist - t))
        return float(eps_vec[idx])

    H1_t = [[Hx, J1_t], [Hz, eps_t]]
    H2_t = [[Hx, J2_t], [Hz, eps_t]]
    try:
        psi0 = qtp.basis(2, 0)
        res1 = qtp.mesolve(H1_t, psi0, tlist, [], [])  # ,progress_bar=False )
        res2 = qtp.mesolve(H2_t, psi0, tlist, [], [])  # ,progress_bar=False )
    except Exception as e:
        logging.warning(e)
        # This is exception handling to be able to use this in a loop
        return 0, 0

    phases1 = (ket_to_phase(res1.states) % (2 * np.pi)) / (2 * np.pi) * 360
    phases2 = (ket_to_phase(res2.states) % (2 * np.pi)) / (2 * np.pi) * 360
    phase_diff_deg = (phases2 - phases1) % 360
    leakage_vec = np.zeros(len(res2.states))
    for i in range(len(res2.states)):
        leakage_vec[i] = 1 - (psi0.dag() * res2.states[i]).norm()

    leakage = leakage_vec[-1]
    picked_up_phase = phase_diff_deg[-1]
    if verbose:
        print('Picked up phase: {:.1f} (deg) \nLeakage: \t {:.3f} (%)'.format(
            picked_up_phase, leakage * 100))
    if return_all:
        return picked_up_phase, leakage, res1, res2, eps_vec, tlist
    else:
        return picked_up_phase, leakage
示例#14
0
    def test_time_dependent_fast_adiabatic_pulse(self):

        # Hamiltonian pars
        alpha_q0 = 250e6 * 2 * np.pi
        J = 2.5e6 * 2 * np.pi
        w_q0 = 6e9 * 2 * np.pi
        w_q1 = 7e9 * 2 * np.pi

        H_0 = czu.coupled_transmons_hamiltonian(w_q0,
                                                w_q1,
                                                alpha_q0=alpha_q0,
                                                J=J)

        # Parameters
        f_interaction = w_q0 + alpha_q0
        f_01_max = w_q1

        length = 240e-9
        sampling_rate = 2.4e9
        lambda_2 = 0
        lambda_3 = 0
        V_per_phi0 = 2
        E_c = 250e6
        theta_f = 85

        J2 = J * np.sqrt(2)

        tlist = (np.arange(0, length, 1 / sampling_rate))

        f_pulse = martinis_flux_pulse(length,
                                      lambda_2=lambda_2,
                                      lambda_3=lambda_3,
                                      theta_f=theta_f,
                                      f_01_max=f_01_max,
                                      E_c=E_c,
                                      V_per_phi0=V_per_phi0,
                                      f_interaction=f_interaction,
                                      J2=J2,
                                      return_unit='f01',
                                      sampling_rate=sampling_rate)
        eps_vec = f_pulse - w_q1

        def eps_t(t, args=None):
            idx = np.argmin(abs(tlist - t))
            return float(eps_vec[idx])

        H_c = czu.n_q1
        H_t = [H_0, [H_c, eps_t]]

        # Calculate the trajectory
        t0 = time.time()
        U_t = qtp.propagator(H_t, tlist)
        t1 = time.time()
        print('simulation took {:.2f}s'.format(t1 - t0))

        test_indices = range(len(tlist))[::50]
        phases = np.asanyarray([
            czu.phases_from_unitary(
                czu.rotating_frame_transformation(U_t[t_idx], tlist[t_idx],
                                                  w_q0, w_q1))
            for t_idx in test_indices
        ])
        t2 = time.time()
        print('Extracting phases took {:.2f}s'.format(t2 - t1))

        cond_phases = phases[:, 4]
        expected_phases = np.array([
            0., 356.35610703, 344.93107947, 326.69596131, 303.99108914,
            279.5479871, 254.95329258, 230.67722736, 207.32417721,
            186.68234108, 171.38527544, 163.55444707
        ])
        np.testing.assert_array_almost_equal(cond_phases, expected_phases)

        L1 = [czu.leakage_from_unitary(U_t[t_idx]) for t_idx in test_indices]
        L2 = [czu.seepage_from_unitary(U_t[t_idx]) for t_idx in test_indices]

        expected_L1 = np.array([
            0.0, 0.026757049282008727, 0.06797292824458401,
            0.09817896580396734, 0.11248845556751286, 0.11574586085284067,
            0.11484563049326857, 0.11243390482702287, 0.1047153697736567,
            0.08476542786503238, 0.04952861565413047, 0.00947869831231718
        ])
        # This condition holds for unital (and unitary) processes and depends
        # on the dimension of the subspace see Woods Gambetta 2018
        expected_L2 = 2 * expected_L1
        np.testing.assert_array_almost_equal(L1, expected_L1)
        np.testing.assert_array_almost_equal(L2, expected_L2)