def Flipping_seq(N, pulse_pars, RO_pars, verbose=False, upload=True, cal_points=True, return_seq=False): ''' Flipping sequence for a single qubit using the tektronix. Input pars: N: array of number of flips (int) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters ''' seq_name = 'Flipping_sequence' seq = sequence.Sequence(seq_name) el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) for tt, n in enumerate(N): # seq has to have at least 2 elts if cal_points and tt > (len(N) - 5): if (tt == (len(N) - 4) or tt == (len(N) - 3)): el = multi_pulse_elt(n, station, [pulses['I'], RO_pars]) elif (tt == (len(N) - 2) or tt == (len(N) - 1)): el = multi_pulse_elt(n, station, [pulses['X180'], RO_pars]) else: pulse_list = [pulses['X90']] + (n) * [pulses['X180']] + [RO_pars] el = multi_pulse_elt(n, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def Echo_seq(times, pulse_pars, RO_pars, artificial_detuning=None, cal_points=True, verbose=False, upload=True, return_seq=False): ''' Echo sequence for a single qubit using the tektronix. Input pars: times: array of times between (start of) pulses (s) artificial_detuning: artificial_detuning (Hz) implemented using phase pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters cal_points: whether to use calibration points or not ''' print('sequencing') seq_name = 'Echo_sequence' seq = sequence.Sequence(seq_name) el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) center_X180 = deepcopy(pulses['X180']) final_X90 = deepcopy(pulses['X90']) # first_X90 = deepcopy(pulses['X90']) # first_X90['refpoint']='start' # #start the second pulse tau/2 from the END of the previous pulse center_X180['refpoint'] = 'end' #start the third pulse tau/2 from the END of the second pulse final_X90['refpoint'] = 'end' for i, tau in enumerate(times): center_X180['pulse_delay'] = tau / 2 final_X90['pulse_delay'] = tau / 2 if artificial_detuning is not None: final_X90['phase'] = (tau - times[0]) * artificial_detuning * 360 if cal_points and (i == (len(times) - 4) or i == (len(times) - 3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(times) - 2) or i == (len(times) - 1)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: el = multi_pulse_elt( i, station, [pulses['X90'], center_X180, final_X90, RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Ramsey_seq(times, pulse_pars, RO_pars, artificial_detuning=None, cal_points=True, verbose=False, upload=True, return_seq=False): ''' Ramsey sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: times: array of times between (start of) pulses (s) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters artificial_detuning: artificial_detuning (Hz) implemented using phase cal_points: whether to use calibration points or not ''' seq_name = 'Ramsey_sequence' seq = sequence.Sequence(seq_name) el_list = [] # First extract values from input, later overwrite when generating # waveforms pulses = get_pulse_dict_from_pars(pulse_pars) #Set up the 'return'-pulse to return to 0 pulse_pars_x2 = deepcopy(pulses['X90']) #Evolve tau from the END of the first pulse pulse_pars_x2['refpoint'] = 'end' for i, tau in enumerate(times): pulse_pars_x2['pulse_delay'] = tau if artificial_detuning is not None: Dphase = ((tau - times[0]) * artificial_detuning * 360) % 360 pulse_pars_x2['phase'] = Dphase if cal_points and (i == (len(times) - 4) or i == (len(times) - 3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(times) - 2) or i == (len(times) - 1)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: el = multi_pulse_elt(i, station, [pulses['X90'], pulse_pars_x2, RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Motzoi_XY(motzois, pulse_pars, RO_pars, cal_points=True, verbose=False, upload=True, return_seq=False): ''' Sequence used for calibrating the motzoi parameter. Consists of Xy and Yx Beware that the elements alternate, if you want to measure both Xy and Yx at each motzoi you need repeating motzoi parameters. This was chosen to be more easily compatible with standard detector functions and sweep pts Input pars: motzois: array of motzoi parameters pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters cal_points: if True, replaces the last 2*4 segments with calibration points ''' seq_name = 'MotzoiXY' seq = sequence.Sequence(seq_name) el_list = [] pulse_combinations = [['X180', 'Y90'], ['Y180', 'X90']] pulses = get_pulse_dict_from_pars(pulse_pars) for i, motzoi in enumerate(motzois): pulse_keys = pulse_combinations[i % 2] for p_name in ['X180', 'Y180', 'X90', 'Y90']: pulses[p_name]['motzoi'] = motzoi if cal_points and (i == (len(motzois) - 4) or i == (len(motzois) - 3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(motzois) - 2) or i == (len(motzois) - 1)): # pick motzoi for calpoint in the middle of the range pulses['X180']['motzoi'] = np.mean(motzois) el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: pulse_list = [pulses[x] for x in pulse_keys] pulse_list += [RO_pars] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Motzoi_XY(motzois, pulse_pars, RO_pars, cal_points=True, verbose=False, upload=True, return_seq=False): ''' Sequence used for calibrating the motzoi parameter. Consists of Xy and Yx Beware that the elements alternate, if you want to measure both Xy and Yx at each motzoi you need repeating motzoi parameters. This was chosen to be more easily compatible with standard detector functions and sweep pts Input pars: motzois: array of motzoi parameters pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters cal_points: if True, replaces the last 2*4 segments with calibration points ''' seq_name = 'MotzoiXY' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulse_combinations = [['X180', 'Y90'], ['Y180', 'X90']] pulses = get_pulse_dict_from_pars(pulse_pars) for i, motzoi in enumerate(motzois): pulse_keys = pulse_combinations[i % 2] for p_name in ['X180', 'Y180', 'X90', 'Y90']: pulses[p_name]['motzoi'] = motzoi if cal_points and (i == (len(motzois)-4) or i == (len(motzois)-3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(motzois)-2) or i == (len(motzois)-1)): # pick motzoi for calpoint in the middle of the range pulses['X180']['motzoi'] = np.mean(motzois) el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: pulse_list = [pulses[x] for x in pulse_keys] pulse_list += [RO_pars] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Ramsey_2nd_exc_seq(times, pulse_pars, pulse_pars_2nd, RO_pars, n=1, cal_points=True, post_msmt_delay=3e-6, verbose=False): ''' Rabi sequence for the second excited state Input pars: amps: array of pulse amplitudes (V) pulse_pars: dict containing the pulse parameters pulse_pars_2nd: dict containing pulse_parameters for 2nd exc. state RO_pars: dict containing the RO parameters n: number of pulses (1 is conventional Rabi) post_msmt_delay: extra wait time for resetless compatibility ''' seq_name = 'Ramsey_2nd_exc_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) pulses_2nd = get_pulse_dict_from_pars(pulse_pars_2nd) for i, tau in enumerate(times): if cal_points and (i == (len(times) - 6) or i == (len(times) - 5)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(times) - 4) or i == (len(times) - 3)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) elif cal_points and (i == (len(times) - 2) or i == (len(times) - 1)): el = multi_pulse_elt(i, station, [pulses['X180'], pulses['X180'], RO_pars]) else: pulse_pars_x2 = deepcopy(pulses_2nd['X90']) pulse_pars_x2['pulse_delay'] = tau pulse_list = ([pulses['X180']] + n * [pulses_2nd['X90'], pulse_pars_x2] + [pulses['X180'], RO_pars]) # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += post_msmt_delay el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) station.pulsar.program_awgs(seq, *el_list, verbose=verbose) return seq_name
def GST_from_textfile(pulse_pars, RO_pars, filename, upload=True, seq_name=None, verbose=False): ''' Input pars: pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters filename: name of a pygsti generated text file upload: upload to AWG or not, if returns seq, el_list ''' if seq_name is None: seq_name = 'GST_seq' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses pulse_dict = get_pulse_dict_from_pars(pulse_pars) pulse_dict['RO'] = RO_pars pulse_combinations = create_experiment_list_pyGSTi_general(filename) for i, pulse_comb in enumerate(pulse_combinations): pulse_list = [] for pulse_key in pulse_comb: pulse_list += [pulse_dict[pulse_key]] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) return seq, el_list
def Pulsed_spec_seq(RO_pars, spec_marker_channels, spec_pulse_length=1e-6, marker_interval=4e-6, verbose=False, trigger_wait=True): seq_name = 'Pulsed_spec_with_RF_mod' seq = sequence.Sequence(seq_name) RO_pars = deepcopy(RO_pars) spec_pulse_start = ( marker_interval - (RO_pars['pulse_delay'] + RO_pars['length'])) print(spec_pulse_start) RO_pars['pulse_delay'] += spec_pulse_length if spec_pulse_start < 0: err_str = ('marker_interval {} must'.format(marker_interval) + 'be larger than length of RO element') raise ValueError(err_str) marker_pars = {'pulse_type': 'SquarePulse', 'length': spec_pulse_length, 'amplitude': 1, 'channels': spec_marker_channels, 'pulse_delay': spec_pulse_start} print(spec_pulse_length) el_list = [] for i in range(2): el = multi_pulse_elt(i, station, [marker_pars, RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=trigger_wait) # Ensures a continuously running sequence station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose)
def Rising_seq(amps, pulse_pars, RO_pars, n=1, post_msmt_delay=3e-6, verbose=False, upload=True, return_seq=False): ''' Rabi sequence for a single qubit using the tektronix. Input pars: amps: array of pulse amplitudes (V) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters n: number of pulses (1 is conventional Rabi) post_msmt_delay: extra wait time for resetless compatibility ''' seq_name = 'Rising_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulse_pars = {'pulse_type':'RisingPulse'} pulse_list = [pulse_pars] el = multi_pulse_elt(0, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq,el_list else: return seq
def Rabi_amp90_seq(scales, pulse_pars, RO_pars, n=1, post_msmt_delay=3e-6, verbose=False, upload=True, return_seq=False): ''' Rabi sequence to determine amp90 scaling factor for a single qubit using the tektronix. Input pars: scales: array of amp90 scaling parameters pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters n: number of pulses (1 is 2 pi half pulses) post_msmt_delay: extra wait time for resetless compatibility ''' seq_name = 'Rabi_amp90_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) for i, scale in enumerate(scales): # seq has to have at least 2 elts pulses['X90']['amplitude'] = pulses['X180']['amplitude'] *scale pulse_list = 2*n*[pulses['X90']]+[RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += post_msmt_delay el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def GST_from_textfile(pulse_pars, RO_pars, filename, upload=True, seq_name=None, verbose=False): ''' Input pars: pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters filename: name of a pygsti generated text file upload: upload to AWG or not, if returns seq, el_list ''' if seq_name is None: seq_name = 'GST_seq' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses pulse_dict = get_pulse_dict_from_pars(pulse_pars) pulse_dict['RO'] = RO_pars pulse_combinations = create_experiment_list_pyGSTi_general(filename) for i, pulse_comb in enumerate(pulse_combinations): pulse_list = [] for pulse_key in pulse_comb: pulse_list += [pulse_dict[pulse_key]] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq, el_list
def four_qubit_off_on(q0_pulse_pars, q1_pulse_pars, q2_pulse_pars, q3_pulse_pars, RO_pars, return_seq=False, verbose=False): seq_name = '4_qubit_OffOn_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses q0_pulses = add_suffix_to_dict_keys( get_pulse_dict_from_pars(q0_pulse_pars), ' q0') q1_pulses = add_suffix_to_dict_keys( get_pulse_dict_from_pars(q1_pulse_pars), ' q1') q2_pulses = add_suffix_to_dict_keys( get_pulse_dict_from_pars(q2_pulse_pars), ' q2') q3_pulses = add_suffix_to_dict_keys( get_pulse_dict_from_pars(q3_pulse_pars), ' q3') RO_dict = {'RO': RO_pars} pulse_dict = {} pulse_dict.update(q0_pulses) pulse_dict.update(q1_pulses) pulse_dict.update(q2_pulses) pulse_dict.update(q3_pulses) pulse_dict.update(RO_dict) # N.B. Identities not needed in all cases pulse_combinations = [['I q0', 'I q1', 'I q2', 'I q3', 'RO'], ['X180 q0', 'I q1', 'I q2', 'I q3', 'RO'], ['I q0', 'X180 q1', 'I q2', 'I q3', 'RO'], ['X180 q0', 'X180 q1', 'I q2', 'I q3', 'RO'], ['I q0', 'I q1', 'X180 q2', 'I q3', 'RO'], ['X180 q0', 'I q1', 'X180 q2', 'I q3', 'RO'], ['I q0', 'X180 q1', 'X180 q2', 'I q3', 'RO'], ['X180 q0', 'X180 q1', 'X180 q2', 'I q3', 'RO'], ['I q0', 'I q1', 'I q2', 'X180 q3', 'RO'], ['X180 q0', 'I q1', 'I q2', 'X180 q3', 'RO'], ['I q0', 'X180 q1', 'I q2', 'X180 q3', 'RO'], ['X180 q0', 'X180 q1', 'I q2', 'X180 q3', 'RO'], ['I q0', 'I q1', 'X180 q2', 'X180 q3', 'RO'], ['X180 q0', 'I q1', 'X180 q2', 'X180 q3', 'RO'], ['I q0', 'X180 q1', 'X180 q2', 'X180 q3', 'RO'], ['X180 q0', 'X180 q1', 'X180 q2', 'X180 q3', 'RO']] for i, pulse_comb in enumerate(pulse_combinations): pulses = [] for p in pulse_comb: pulses += [pulse_dict[p]] el = multi_pulse_elt(i, station, pulses) el_list.append(el) seq.append_element(el, trigger_wait=True) station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Pulsed_spec_seq(RO_pars, spec_marker_channels, spec_pulse_length=1e-6, marker_interval=4e-6, verbose=False, trigger_wait=True): seq_name = 'Pulsed_spec_with_RF_mod' seq = sequence.Sequence(seq_name) RO_pars = deepcopy(RO_pars) spec_pulse_start = (marker_interval - (RO_pars['pulse_delay'] + RO_pars['length'])) print(spec_pulse_start) RO_pars['pulse_delay'] += spec_pulse_length if spec_pulse_start < 0: err_str = ('marker_interval {} must'.format(marker_interval) + 'be larger than length of RO element') raise ValueError(err_str) marker_pars = { 'pulse_type': 'SquarePulse', 'length': spec_pulse_length, 'amplitude': 1, 'channels': spec_marker_channels, 'pulse_delay': spec_pulse_start } print(spec_pulse_length) el_list = [] for i in range(2): el = multi_pulse_elt(i, station, [marker_pars, RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=trigger_wait) # Ensures a continuously running sequence station.pulsar.program_awgs(seq, *el_list, verbose=verbose)
def Rising_seq(amps, pulse_pars, RO_pars, n=1, post_msmt_delay=3e-6, verbose=False, upload=True, return_seq=False): ''' Rabi sequence for a single qubit using the tektronix. Input pars: amps: array of pulse amplitudes (V) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters n: number of pulses (1 is conventional Rabi) post_msmt_delay: extra wait time for resetless compatibility ''' seq_name = 'Rising_sequence' seq = sequence.Sequence(seq_name) el_list = [] pulse_pars = {'pulse_type': 'RisingPulse'} pulse_list = [pulse_pars] el = multi_pulse_elt(0, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def Ramsey_seq(times, pulse_pars, RO_pars, artificial_detuning=None, cal_points=True, verbose=False, upload=True, return_seq=False): ''' Ramsey sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: times: array of times between (start of) pulses (s) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters artificial_detuning: artificial_detuning (Hz) implemented using phase cal_points: whether to use calibration points or not ''' seq_name = 'Ramsey_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # First extract values from input, later overwrite when generating waveforms pulses = get_pulse_dict_from_pars(pulse_pars) pulse_pars_x2 = deepcopy(pulses['X90']) pulse_pars_x2['refpoint'] = 'start' for i, tau in enumerate(times): pulse_pars_x2['pulse_delay'] = tau if artificial_detuning is not None: Dphase = ((tau-times[0]) * artificial_detuning * 360) % 360 pulse_pars_x2['phase'] = Dphase if cal_points and (i == (len(times)-4) or i == (len(times)-3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(times)-2) or i == (len(times)-1)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: el = multi_pulse_elt(i, station, [pulses['X90'], pulse_pars_x2, RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Echo_seq(times, pulse_pars, RO_pars, artificial_detuning=None, cal_points=True, verbose=False, upload=True, return_seq=False): ''' Echo sequence for a single qubit using the tektronix. Input pars: times: array of times between (start of) pulses (s) artificial_detuning: artificial_detuning (Hz) implemented using phase pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters cal_points: whether to use calibration points or not ''' seq_name = 'Echo_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) center_X180 = deepcopy(pulses['X180']) final_X90 = deepcopy(pulses['X90']) center_X180['refpoint'] = 'start' final_X90['refpoint'] = 'start' for i, tau in enumerate(times): center_X180['pulse_delay'] = tau/2 final_X90['pulse_delay'] = tau/2 if artificial_detuning is not None: final_X90['phase'] = (tau-times[0]) * artificial_detuning * 360 if cal_points and (i == (len(times)-4) or i == (len(times)-3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(times)-2) or i == (len(times)-1)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: el = multi_pulse_elt(i, station, [pulses['X90'], center_X180, final_X90, RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Ramsey_2nd_exc_seq(times, pulse_pars, pulse_pars_2nd, RO_pars, n=1, cal_points=True, post_msmt_delay=3e-6, verbose=False): ''' Rabi sequence for the second excited state Input pars: amps: array of pulse amplitudes (V) pulse_pars: dict containing the pulse parameters pulse_pars_2nd: dict containing pulse_parameters for 2nd exc. state RO_pars: dict containing the RO parameters n: number of pulses (1 is conventional Rabi) post_msmt_delay: extra wait time for resetless compatibility ''' seq_name = 'Ramsey_2nd_exc_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) pulses_2nd = get_pulse_dict_from_pars(pulse_pars_2nd) for i, tau in enumerate(times): if cal_points and (i == (len(times)-6) or i == (len(times)-5)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(times)-4) or i == (len(times)-3)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) elif cal_points and (i == (len(times)-2) or i == (len(times)-1)): el = multi_pulse_elt(i, station, [pulses['X180'], pulses['X180'], RO_pars]) else: pulse_pars_x2 = deepcopy(pulses_2nd['X90']) pulse_pars_x2['pulse_delay'] = tau pulse_list = ([pulses['X180']]+n*[pulses_2nd['X90'], pulse_pars_x2] + [pulses['X180'], RO_pars]) # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += post_msmt_delay el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq_name
def test_operation_dependent_buffers_and_compensation(self): # Fixed point should shift both elements by 2 ns RO_amp = 0.1 MW_amp = 0.3 Flux_amp = 0.5 operation_dict = {'RO q0': {'amplitude': RO_amp, 'length': 300e-9, 'operation_type': 'RO', 'channel': 'ch1', 'pulse_delay': 0, 'pulse_type': 'SquarePulse'}, 'MW q0': {'amplitude': MW_amp, 'length': 20e-9, 'operation_type': 'MW', 'channel': 'ch1', 'pulse_delay': 0, 'pulse_type': 'SquarePulse'}, 'Flux q0': {'amplitude': Flux_amp, 'length': 40e-9, 'operation_type': 'Flux', 'channel': 'ch1', 'pulse_delay': 0, 'pulse_type': 'SquarePulse'}, 'sequencer_config': {'Buffer_Flux_Flux': 1e-9, 'Buffer_Flux_MW': 2e-9, 'Buffer_Flux_RO': 3e-9, 'Buffer_MW_Flux': 4e-9, 'Buffer_MW_MW': 5e-9, 'Buffer_MW_RO': 6e-9, 'Buffer_RO_Flux': 7e-9, 'Buffer_RO_MW': 8e-9, 'Buffer_RO_RO': 10e-9, 'RO_fixed_point': 1e-06, 'Flux_comp_dead_time': 3e-6}} sequencer_config = operation_dict['sequencer_config'] fake_seq = ['MW q0', 'MW q0', 'Flux q0', 'MW q0', 'RO q0'] pulses = [] for p in fake_seq: pulses += [operation_dict[p]] test_elt = multi_pulse_elt(0, self.station, pulses, sequencer_config) min_samples = 1800+3040 # 1us fixpoint, 300ns RO pulse and 4ns zeros ch1_wf = test_elt.waveforms()[1]['ch1'] self.assertEqual(len(ch1_wf), min_samples) expected_wf = np.zeros(min_samples) expected_wf[1000:1300] = RO_amp expected_wf[974:994] = MW_amp expected_wf[932:972] = Flux_amp expected_wf[908:928] = MW_amp expected_wf[883:903] = MW_amp expected_wf[4300:4340] = -Flux_amp np.testing.assert_array_almost_equal(ch1_wf, expected_wf)
def Butterfly_seq(pulse_pars, RO_pars, initialize=False, post_msmt_delay=2000e-9, upload=True, verbose=False): ''' Butterfly sequence to measure single shot readout fidelity to the pre-and post-measurement state. This is the way to veify the QND-ness off the measurement. - Initialize adds an exta measurement before state preparation to allow initialization by post-selection - Post-measurement delay can be varied to correct data for Tone effects. Post-measurement delay should be sufficiently long to avoid photon-induced gate errors when post-selecting. ''' seq_name = 'Butterfly_seq' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses pulses = get_pulse_dict_from_pars(pulse_pars) fixed_point_freq = RO_pars['fixed_point_frequency'] RO_pars['fixed_point_frequency'] = None pulses['RO'] = RO_pars pulse_lists = ['', ''] pulses['I_wait'] = deepcopy(pulses['I']) pulses['I_wait']['pulse_delay'] = post_msmt_delay if initialize: pulse_lists[0] = [['I', 'RO'], ['I', 'RO'], ['I', 'RO']] pulse_lists[1] = [['I', 'RO'], ['X180', 'RO'], ['I', 'RO']] else: pulse_lists[0] = [['I', 'RO'], ['I', 'RO']] pulse_lists[1] = [['X180', 'RO'], ['I', 'RO']] for i, pulse_keys_sub_list in enumerate(pulse_lists): pulse_list = [] # sub list exist to make sure the RO-s are in phase for pulse_keys in pulse_keys_sub_list: pulse_sub_list = [pulses[key] for key in pulse_keys] sub_seq_duration = sum([p['pulse_delay'] for p in pulse_sub_list]) if fixed_point_freq==None: extra_delay = 0 else: extra_delay = calculate_time_correction( sub_seq_duration+post_msmt_delay, fixed_point_freq) initial_pulse_delay = post_msmt_delay + extra_delay start_pulse = deepcopy(pulse_sub_list[0]) start_pulse['pulse_delay'] += initial_pulse_delay pulse_sub_list[0] = start_pulse pulse_list += pulse_sub_list el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq_name
def four_qubit_off_on( q0_pulse_pars, q1_pulse_pars, q2_pulse_pars, q3_pulse_pars, RO_pars, return_seq=False, verbose=False ): seq_name = "4_qubit_OffOn_sequence" seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses q0_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q0_pulse_pars), " q0") q1_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q1_pulse_pars), " q1") q2_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q2_pulse_pars), " q2") q3_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q3_pulse_pars), " q3") RO_dict = {"RO": RO_pars} pulse_dict = {} pulse_dict.update(q0_pulses) pulse_dict.update(q1_pulses) pulse_dict.update(q2_pulses) pulse_dict.update(q3_pulses) pulse_dict.update(RO_dict) # N.B. Identities not needed in all cases pulse_combinations = [ ["I q0", "I q1", "I q2", "I q3", "RO"], ["X180 q0", "I q1", "I q2", "I q3", "RO"], ["I q0", "X180 q1", "I q2", "I q3", "RO"], ["X180 q0", "X180 q1", "I q2", "I q3", "RO"], ["I q0", "I q1", "X180 q2", "I q3", "RO"], ["X180 q0", "I q1", "X180 q2", "I q3", "RO"], ["I q0", "X180 q1", "X180 q2", "I q3", "RO"], ["X180 q0", "X180 q1", "X180 q2", "I q3", "RO"], ["I q0", "I q1", "I q2", "X180 q3", "RO"], ["X180 q0", "I q1", "I q2", "X180 q3", "RO"], ["I q0", "X180 q1", "I q2", "X180 q3", "RO"], ["X180 q0", "X180 q1", "I q2", "X180 q3", "RO"], ["I q0", "I q1", "X180 q2", "X180 q3", "RO"], ["X180 q0", "I q1", "X180 q2", "X180 q3", "RO"], ["I q0", "X180 q1", "X180 q2", "X180 q3", "RO"], ["X180 q0", "X180 q1", "X180 q2", "X180 q3", "RO"], ] for i, pulse_comb in enumerate(pulse_combinations): pulses = [] for p in pulse_comb: pulses += [pulse_dict[p]] el = multi_pulse_elt(i, station, pulses) el_list.append(el) seq.append_element(el, trigger_wait=True) station.components["AWG"].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Butterfly_seq(pulse_pars, RO_pars, initialize=False, post_msmt_delay=2000e-9, upload=True, verbose=False): ''' Butterfly sequence to measure single shot readout fidelity to the pre-and post-measurement state. This is the way to veify the QND-ness off the measurement. - Initialize adds an exta measurement before state preparation to allow initialization by post-selection - Post-measurement delay can be varied to correct data for Tone effects. Post-measurement delay should be sufficiently long to avoid photon-induced gate errors when post-selecting. ''' seq_name = 'Butterfly_seq' seq = sequence.Sequence(seq_name) el_list = [] # Create a dict with the parameters for all the pulses pulses = get_pulse_dict_from_pars(pulse_pars) pulses['RO'] = RO_pars pulse_lists = ['', ''] pulses['I_wait'] = deepcopy(pulses['I']) pulses['I_wait']['pulse_delay'] = post_msmt_delay if initialize: pulse_lists[0] = [['I', 'RO'], ['I', 'RO'], ['I', 'RO']] pulse_lists[1] = [['I', 'RO'], ['X180', 'RO'], ['I', 'RO']] else: pulse_lists[0] = [['I', 'RO'], ['I', 'RO']] pulse_lists[1] = [['X180', 'RO'], ['I', 'RO']] for i, pulse_keys_sub_list in enumerate(pulse_lists): pulse_list = [] # sub list exist to make sure the RO-s are in phase for pulse_keys in pulse_keys_sub_list: pulse_sub_list = [pulses[key] for key in pulse_keys] sub_seq_duration = sum([p['pulse_delay'] for p in pulse_sub_list]) if RO_pars['f_RO_mod'] == None: extra_delay = 0 else: extra_delay = calculate_time_correction( sub_seq_duration + post_msmt_delay, RO_pars['f_RO_mod']) initial_pulse_delay = post_msmt_delay + extra_delay start_pulse = deepcopy(pulse_sub_list[0]) start_pulse['pulse_delay'] += initial_pulse_delay pulse_sub_list[0] = start_pulse pulse_list += pulse_sub_list el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) return seq_name
def cos_seq(amplitude, frequency, channels, phases, marker_channels=None, marker_lenght=20e-9, verbose=False, alphas=[1], phi_skews=[0], ): ''' Cosine sequence, plays a continuous cos on the specified channel Input pars: amplitude (float): amplitude in Vpp frequency (float): frequency in Hz channels (list[(str)]: channels on which to set a cos phases (list[(float)]: phases in degree marker_channels (list[(str)]: optionally specify markers to play ''' seq_name = 'ModSquare' seq = sequence.Sequence(seq_name) el_list = [] base_pars = {'pulse_type': 'ModSquare', 'mod_frequency': frequency, 'length': 2e-6, 'amplitude': amplitude, 'pulse_delay': 0} marker_pars = {'pulse_type': 'SquarePulse', 'length': marker_lenght, 'amplitude': 1, 'pulse_delay': 10e-9} pulse_list = [] for i, phase in enumerate(phases): pulse = deepcopy(base_pars) pulse['I_channel'] = channels[i*2] pulse['Q_channel'] = channels[i*2+1] pulse['phase'] = phase pulse['alpha'] = alphas[i] pulse['phi_skew'] = phi_skews[i] pulse_list.append(pulse) # copy first element and set extra wait if marker_channels !=None: for i, marker_channel in enumerate(marker_channels): pulse = deepcopy(marker_pars) pulse['channel'] = marker_channel if i != 0: pulse['pulse_delay'] = 0 pulse_list.append(pulse) el = multi_pulse_elt(0, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=False) # seq.append_element(el, trigger_wait=False) station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq_name
def T1_seq(times, pulse_pars, RO_pars, cal_points=True, verbose=False, upload=True, return_seq=False): ''' Rabi sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: times: array of times to wait after the initial pi-pulse pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters ''' seq_name = 'T1_sequence' seq = sequence.Sequence(seq_name) el_list = [] #RO_pulse_delay = amount of time for pulse to end RO_pulse_delay = RO_pars['pulse_delay'] RO_pars = deepcopy(RO_pars) # Prevents overwriting of the dict pulses = get_pulse_dict_from_pars(pulse_pars) for i, tau in enumerate(times): # seq has to have at least 2 elts RO_pars['pulse_delay'] = RO_pulse_delay + tau RO_pars['refpoint'] = 'start' # time defined between start of ops if cal_points: if (i == (len(times) - 4) or i == (len(times) - 3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif (i == (len(times) - 2) or i == (len(times) - 1)): RO_pars['pulse_delay'] = RO_pulse_delay el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Flipping_seq(pulse_pars, RO_pars, n=1, post_msmt_delay=10e-9, verbose=False, upload=True, return_seq=False): ''' Flipping sequence for a single qubit using the tektronix. Input pars: pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters n: iterations (up to 2n+1 pulses) post_msmt_delay: extra wait time for resetless compatibility ''' seq_name = 'Flipping_sequence' seq = sequence.Sequence(seq_name) el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) RO_pulse_delay = RO_pars['pulse_delay'] for i in range(n + 4): # seq has to have at least 2 elts if (i == (n + 1) or i == (n)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif (i == (n + 3) or i == (n + 2)): RO_pars['pulse_delay'] = RO_pulse_delay el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: pulse_list = [pulses['X90'] ] + (2 * i + 1) * [pulses['X180']] + [RO_pars] # # copy first element and set extra wait # pulse_list[0] = deepcopy(pulse_list[0]) # pulse_list[0]['pulse_delay'] += post_msmt_delay el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def T1_seq(times, pulse_pars, RO_pars, cal_points=True, verbose=False, upload=True, return_seq=False): ''' Rabi sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: times: array of times to wait after the initial pi-pulse pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters ''' seq_name = 'T1_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] RO_pulse_delay = RO_pars['pulse_delay'] RO_pars = deepcopy(RO_pars) # Prevents overwriting of the dict pulses = get_pulse_dict_from_pars(pulse_pars) for i, tau in enumerate(times): # seq has to have at least 2 elts RO_pars['pulse_delay'] = RO_pulse_delay + tau RO_pars['refpoint'] = 'start' # time defined between start of ops if cal_points: if (i == (len(times)-4) or i == (len(times)-3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif(i == (len(times)-2) or i == (len(times)-1)): RO_pars['pulse_delay'] = RO_pulse_delay el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Flipping_seq(pulse_pars, RO_pars, n=1, post_msmt_delay=10e-9, verbose=False, upload=True, return_seq=False): ''' Flipping sequence for a single qubit using the tektronix. Input pars: pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters n: iterations (up to 2n+1 pulses) post_msmt_delay: extra wait time for resetless compatibility ''' seq_name = 'Flipping_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) RO_pulse_delay = RO_pars['pulse_delay'] for i in range(n+4): # seq has to have at least 2 elts if (i == (n+1) or i == (n)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif(i == (n+3) or i == (n+2)): RO_pars['pulse_delay'] = RO_pulse_delay el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: pulse_list = [pulses['X90']]+(2*i+1)*[pulses['X180']]+[RO_pars] # # copy first element and set extra wait # pulse_list[0] = deepcopy(pulse_list[0]) # pulse_list[0]['pulse_delay'] += post_msmt_delay el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def n_qubit_off_on(pulse_pars_list, RO_pars, return_seq=False, verbose=False, parallel_pulses=False, preselection=False, RO_spacing=200e-9): n = len(pulse_pars_list) seq_name = '{}_qubit_OffOn_sequence'.format(n) seq = sequence.Sequence(seq_name) el_list = [] # Create a dict with the parameters for all the pulses pulse_dict = {'RO': RO_pars} for i, pulse_pars in enumerate(pulse_pars_list): pars = pulse_pars.copy() if i != 0 and parallel_pulses: pars['refpoint'] = 'start' pulses = add_suffix_to_dict_keys( get_pulse_dict_from_pars(pars), ' {}'.format(i)) pulse_dict.update(pulses) spacerpulse = {'pulse_type': 'SquarePulse', 'channel': RO_pars['acq_marker_channel'], 'amplitude': 0.0, 'length': RO_spacing, 'pulse_delay': 0} pulse_dict.update({'spacer': spacerpulse}) # Create a list of required pulses pulse_combinations = [] for pulse_list in itertools.product(*(n*[['I', 'X180']])): pulse_comb = (n+1)*[''] for i, pulse in enumerate(pulse_list): pulse_comb[i] = pulse + ' {}'.format(i) pulse_comb[-1] = 'RO' if preselection: pulse_comb = ['RO', 'spacer'] + pulse_comb pulse_combinations.append(pulse_comb) for i, pulse_comb in enumerate(pulse_combinations): pulses = [] for j, p in enumerate(pulse_comb): pulses += [pulse_dict[p]] el = multi_pulse_elt(i, station, pulses) el_list.append(el) seq.append_element(el, trigger_wait=True) station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def Pulsed_spec_seq(spec_pars, RO_pars, upload=True, return_seq=False): ''' Pulsed spectroscopy sequence using the tektronix. Input pars: spec_pars: dict containing spectroscopy pars RO_pars: dict containing RO pars ''' period = spec_pars['pulse_delay'] + RO_pars['pulse_delay'] fixed_point_freq = RO_pars['fixed_point_frequency'] if fixed_point_freq==None: remainder = 0.0 else: remainder = period % (1/RO_pars['fixed_point_frequency']) if (remainder != 0.0): msg = ('Period of spec seq ({})'.format(period) + 'must be multiple of RO modulation period ({})'.format( 1/RO_pars['fixed_point_frequency']) + "\nAdding {}s to spec_pars['pulse_delay']".format( 1/RO_pars['fixed_point_frequency'] - remainder) + '\nConsider updating parameter') logging.warning(msg) print(msg) spec_pars['pulse_delay'] += 1/RO_pars['fixed_point_frequency'] - remainder # Nr of pulse reps is set to ensure max nr of pulses and end 10us before # next trigger comes in. Assumes 200us trigger period, also works for # faster trigger rates. period = spec_pars['pulse_delay'] + RO_pars['pulse_delay'] nr_of_pulse_reps = int((200e-6-10e-6)//period) seq_name = 'Pulsed_spec' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulse_dict = {'spec_pulse': spec_pars, 'RO': RO_pars} pulse_list = [pulse_dict['spec_pulse'], pulse_dict['RO']]*nr_of_pulse_reps for i in range(1): el = multi_pulse_elt( i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=False) return seq
def Pulsed_spec_seq(spec_pars, RO_pars, upload=True, return_seq=False): ''' Pulsed spectroscopy sequence using the tektronix. Input pars: spec_pars: dict containing spectroscopy pars RO_pars: dict containing RO pars ''' period = spec_pars['pulse_delay'] + RO_pars['pulse_delay'] f_RO_mod = RO_pars['f_RO_mod'] if f_RO_mod == None: remainder = 0.0 else: remainder = period % (1 / RO_pars['f_RO_mod']) if (remainder != 0.0): msg = ('Period of spec seq ({})'.format(period) + 'must be multiple of RO modulation period ({})'.format( 1 / RO_pars['f_RO_mod']) + "\nAdding {}s to spec_pars['pulse_delay']".format( 1 / RO_pars['f_RO_mod'] - remainder) + '\nConsider updating parameter') logging.warning(msg) print(msg) spec_pars['pulse_delay'] += 1 / \ RO_pars['f_RO_mod'] - remainder # Nr of pulse reps is set to ensure max nr of pulses and end 10us before # next trigger comes in. Assumes 200us trigger period, also works for # faster trigger rates. period = spec_pars['pulse_delay'] + RO_pars['pulse_delay'] nr_of_pulse_reps = int((200e-6 - 10e-6) // period) seq_name = 'Pulsed_spec' seq = sequence.Sequence(seq_name) el_list = [] pulse_dict = {'spec_pulse': spec_pars, 'RO': RO_pars} pulse_list = [pulse_dict['spec_pulse'], pulse_dict['RO'] ] * nr_of_pulse_reps for i in range(1): el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=False) return seq
def AllXY_seq(pulse_pars, RO_pars, double_points=False, verbose=False, upload=True, return_seq=False): ''' AllXY sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters ''' seq_name = 'AllXY_seq' seq = sequence.Sequence(seq_name) el_list = [] # Create a dict with the parameters for all the pulses pulses = get_pulse_dict_from_pars(pulse_pars) pulse_combinations = [['I', 'I'], ['X180', 'X180'], ['Y180', 'Y180'], ['X180', 'Y180'], ['Y180', 'X180'], ['X90', 'I'], ['Y90', 'I'], ['X90', 'Y90'], ['Y90', 'X90'], ['X90', 'Y180'], ['Y90', 'X180'], ['X180', 'Y90'], ['Y180', 'X90'], ['X90', 'X180'], ['X180', 'X90'], ['Y90', 'Y180'], ['Y180', 'Y90'], ['X180', 'I'], ['Y180', 'I'], ['X90', 'X90'], ['Y90', 'Y90']] if double_points: pulse_combinations = [ val for val in pulse_combinations for _ in (0, 1) ] for i, pulse_comb in enumerate(pulse_combinations): pulse_list = [pulses[pulse_comb[0]], pulses[pulse_comb[1]], RO_pars] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def AllXY_seq(pulse_pars, RO_pars, double_points=False, verbose=False, upload=True, return_seq=False): ''' AllXY sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters ''' seq_name = 'AllXY_seq' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses pulses = get_pulse_dict_from_pars(pulse_pars) pulse_combinations = [['I', 'I'], ['X180', 'X180'], ['Y180', 'Y180'], ['X180', 'Y180'], ['Y180', 'X180'], ['X90', 'I'], ['Y90', 'I'], ['X90', 'Y90'], ['Y90', 'X90'], ['X90', 'Y180'], ['Y90', 'X180'], ['X180', 'Y90'], ['Y180', 'X90'], ['X90', 'X180'], ['X180', 'X90'], ['Y90', 'Y180'], ['Y180', 'Y90'], ['X180', 'I'], ['Y180', 'I'], ['X90', 'X90'], ['Y90', 'Y90']] if double_points: pulse_combinations = [val for val in pulse_combinations for _ in (0, 1)] for i, pulse_comb in enumerate(pulse_combinations): pulse_list = [pulses[pulse_comb[0]], pulses[pulse_comb[1]], RO_pars] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def OffOn_seq(pulse_pars, RO_pars, verbose=False, pulse_comb='OffOn', upload=True, return_seq=False): ''' OffOn sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters Initialize: adds an exta measurement before state preparation to allow initialization by post-selection Post-measurement delay: should be sufficiently long to avoid photon-induced gate errors when post-selecting. pulse_comb: OffOn/OnOn/OffOff cobmination of pulses to play ''' seq_name = 'OffOn_sequence' seq = sequence.Sequence(seq_name) el_list = [] # Create a dict with the parameters for all the pulses pulses = get_pulse_dict_from_pars(pulse_pars) if pulse_comb == 'OffOn': pulse_combinations = ['I', 'X180'] elif pulse_comb == 'OnOn': pulse_combinations = ['X180', 'X180'] elif pulse_comb == 'OffOff': pulse_combinations = ['I', 'I'] for i, pulse_comb in enumerate(pulse_combinations): el = multi_pulse_elt(i, station, [pulses[pulse_comb], RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def SSRO_2nd_exc_state(pulse_pars, pulse_pars_2nd, RO_pars, verbose=False): seq_name = 'SSRO_2nd_exc' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) pulses_2nd = get_pulse_dict_from_pars(pulse_pars_2nd) # First element pulse_combinations = [[pulses['I']] + [RO_pars]] pulse_combinations += [[pulses['X180']] + [RO_pars]] pulse_combinations += [[pulses['X180']] + [pulses_2nd['X180']] + [RO_pars]] for i, pulse_list in enumerate(pulse_combinations): el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) seq.append_element(el, trigger_wait=True) station.pulsar.program_awgs(seq, *el_list, verbose=verbose) return seq_name
def avoided_crossing_spec_seq(operation_dict, q0, q1, RO_target, verbose=False, upload=True): seq_name = 'avoidec_crossing_spec' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] sequencer_config = operation_dict['sequencer_config'] # N.B. Identities not needed in all cases pulse_combinations = ['X180 '+q0, 'SpecPulse '+q1, 'RO '+RO_target] pulses = [] for p in pulse_combinations: pulses += [operation_dict[p]] el = multi_pulse_elt(0, station, pulses, sequencer_config) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) return seq, el_list
def photon_number_splitting_seq(spec_pars, RO_pars, disp_pars, upload=True, return_seq=False): ''' Pulsed spectroscopy sequence using the tektronix. Input pars: spec_pars: dict containing spectroscopy pars RO_pars: dict containing RO pars ''' period = spec_pars['pulse_delay'] + RO_pars['pulse_delay'] msg = ('Period of spec seq ({})'.format(period) + 'must be multiple of RO modulation period ({})'.format( 1 / RO_pars['f_RO_mod'])) if (period % (1 / RO_pars['f_RO_mod'])) != 0.0: raise ValueError(msg) # Nr of pulse reps is set to ensure max nr of pulses and end 10us before # next trigger comes in. Assumes 200us trigger period, also works for # faster trigger rates. nr_of_pulse_reps = int((200e-6 - 10e-6) // period) seq_name = 'photon_number_spliting' seq = sequence.Sequence(seq_name) el_list = [] pulse_dict = {'disp': disp_pars, 'spec_pulse': spec_pars, 'RO': RO_pars} pulse_list = [ pulse_dict['disp'], pulse_dict['spec_pulse'], pulse_dict['RO'] ] * nr_of_pulse_reps for i in range(2): el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=False) return seq
def SSRO_2nd_exc_state(pulse_pars, pulse_pars_2nd, RO_pars, verbose=False): seq_name = 'SSRO_2nd_exc' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) pulses_2nd = get_pulse_dict_from_pars(pulse_pars_2nd) # First element pulse_combinations = [[pulses['I']]+[RO_pars]] pulse_combinations += [[pulses['X180']] +[RO_pars]] pulse_combinations += [[pulses['X180']]+[pulses_2nd['X180']] +[RO_pars]] for i, pulse_list in enumerate(pulse_combinations): el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) seq.append_element(el, trigger_wait=True) station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq_name
def OffOn_seq(pulse_pars, RO_pars, verbose=False, pulse_comb='OffOn', upload=True, return_seq=False): ''' OffOn sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters Initialize: adds an exta measurement before state preparation to allow initialization by post-selection Post-measurement delay: should be sufficiently long to avoid photon-induced gate errors when post-selecting. pulse_comb: OffOn/OnOn/OffOff cobmination of pulses to play ''' seq_name = 'OffOn_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses pulses = get_pulse_dict_from_pars(pulse_pars) if pulse_comb == 'OffOn': pulse_combinations = ['I', 'X180'] elif pulse_comb == 'OnOn': pulse_combinations = ['X180', 'X180'] elif pulse_comb == 'OffOff': pulse_combinations = ['I', 'I'] for i, pulse_comb in enumerate(pulse_combinations): el = multi_pulse_elt(i, station, [pulses[pulse_comb], RO_pars]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def photon_number_splitting_seq(spec_pars, RO_pars, disp_pars, upload=True, return_seq=False): ''' Pulsed spectroscopy sequence using the tektronix. Input pars: spec_pars: dict containing spectroscopy pars RO_pars: dict containing RO pars ''' period = spec_pars['pulse_delay'] + RO_pars['pulse_delay'] msg = ('Period of spec seq ({})'.format(period) + 'must be multiple of RO modulation period ({})'.format( 1/RO_pars['fixed_point_frequency'])) if (period % (1/RO_pars['fixed_point_frequency']))!=0.0: raise ValueError(msg) # Nr of pulse reps is set to ensure max nr of pulses and end 10us before # next trigger comes in. Assumes 200us trigger period, also works for # faster trigger rates. nr_of_pulse_reps = int((200e-6-10e-6)//period) seq_name = 'Pulsed_spec' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulse_dict = {'disp': disp_pars, 'spec_pulse': spec_pars, 'RO': RO_pars} pulse_list = [pulse_dict['disp'], pulse_dict['spec_pulse'], pulse_dict['RO']]*nr_of_pulse_reps for i in range(2): el = multi_pulse_elt( i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=False) return seq
def Rabi_amp90_seq(scales, pulse_pars, RO_pars, n=1, post_msmt_delay=3e-6, verbose=False, upload=True, return_seq=False): ''' Rabi sequence to determine amp90 scaling factor for a single qubit using the tektronix. Input pars: scales: array of amp90 scaling parameters pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters n: number of pulses (1 is 2 pi half pulses) post_msmt_delay: extra wait time for resetless compatibility ''' seq_name = 'Rabi_amp90_sequence' seq = sequence.Sequence(seq_name) el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) for i, scale in enumerate(scales): # seq has to have at least 2 elts pulses['X90']['amplitude'] = pulses['X180']['amplitude'] * scale pulse_list = 2 * n * [pulses['X90']] + [RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += post_msmt_delay el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def swap_swap_wait(mw_pulse_pars, RO_pars, flux_pulse_pars, phases=np.linspace(0, 720, 41), inter_swap_wait=100e-9, verbose=False, distortion_dict=None, upload=True, cal_points=True): ''' Sequence of 2 swap operations with varying recovery pulse mY90 - swap - idle- swap - rphi90 - RO mw_pulse_pars: (dict) qubit control pulse pars RO_pars: (dict) qubit RO pars flux_pulse_pars: (dict) flux puplse pars inter_swap_wait (float) wait time in seconds between the two swaps phases (list) phases used for the recovery pulse verbose=False: (bool) used for verbosity printing in the pulsar distortion_dict=None: (dict) flux_pulse predistortion kernels upload=True: (bool) uploads to AWG, set False for testing purposes cal_points=True: (bool) wether to use calibration points ''' # To be merged with swap-CP-swap logging.warning('Do not use, I have marked this for deletion -MAR') preloaded_kernels_vec = preload_kernels_func(distortion_dict) # renamed as the dict contains the pulse directly minus_flux_pulse_pars = deepcopy(flux_pulse_pars) minus_flux_pulse_pars['amplitude'] = -flux_pulse_pars['amplitude'] # Pulse is used to set the starting refpoint for the compensation pulses dead_time_pulse_pars = {'pulse_type': 'SquarePulse', 'pulse_delay': flux_pulse_pars['dead_time'], 'channel': flux_pulse_pars['channel'], 'amplitude': 0, 'length': 0.} seq_name = 'swap_swap_wait_seq' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(mw_pulse_pars) # seq has to have at least 2 elts for i, phase in enumerate(phases): if cal_points and (i == (len(phases)-4) or i == (len(phases)-3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(phases)-2) or i == (len(phases)-1)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: # correcting timings recovery_pi2 = deepcopy(pulses['X90']) recovery_pi2['phase'] = phase second_flux_pulse = deepcopy(flux_pulse_pars) second_flux_pulse['pulse_delay'] = inter_swap_wait pulse_list = [pulses['mY90']] + [flux_pulse_pars] + [second_flux_pulse] \ + [recovery_pi2]+[RO_pars] + \ [dead_time_pulse_pars] + [minus_flux_pulse_pars]*2 el = multi_pulse_elt(i, station, pulse_list) if distortion_dict is not None: el = distort_and_compensate( el, distortion_dict, preloaded_kernels_vec) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq, el_list
def swap_CP_swap_2Qubits(mw_pulse_pars_qCP, mw_pulse_pars_qS, flux_pulse_pars_qCP, flux_pulse_pars_qS, RO_pars, distortion_dict, CPhase=True, excitations='both', inter_swap_wait=100e-9, phases=np.linspace(0, 720, 41), verbose=False, upload=True, cal_points=True): ''' Sequence that swaps qS with the bus and does CPhase between qCP and the bus X180 qS - Ym90 qCP - swap qS,B - CPhase qCP,B - swap qS,B - fphi90 qCP - X180 qS - RO qS is the "swap qubit" qCP is the "CPhase qubit" mw_pulse_pars qCP: (dict) qubit control pulse pars mw_pulse_pars qS: (dict) qubit control pulse pars flux_pulse_pars qCP: (dict) flux puplse pars flux_pulse_pars qS: (dict) flux puplse pars RO_pars: (dict) qubit RO pars, ideally a multiplexed readout distortion_dict=None: (dict) flux_pulse predistortion kernels CPhase: (bool) if False replaces CPhase with an identity excitations: (enum) [0, 1, 'both'] whether to put an excitation in the swap qubit, both does the sequence both ways. phases (list) phases used for the recovery pulse inter_swap_wait (float) wait time in seconds between the two swaps verbose=False: (bool) used for verbosity printing in the pulsar upload=True: (bool) uploads to AWG, set False for testing purposes cal_points=True: (bool) wether to use calibration points TODO: - move getting the pulse dict to a single function - default to the single qubit swap-wait-swap sequence if no pulse pars for qCP - Add all four calibration points ''' # ############ This getting pulse dict should be a single function mw_pulses_qCP = add_suffix_to_dict_keys( get_pulse_dict_from_pars(mw_pulse_pars_qCP), ' qCP') mw_pulses_qS = add_suffix_to_dict_keys( get_pulse_dict_from_pars(mw_pulse_pars_qS), ' qS') # This should come out of this dict in a smarter way swap_qCP = {'CPhase qCP': flux_pulse_pars_qCP} swap_qS = {'swap qS': flux_pulse_pars_qS} RO_dict = {'RO': RO_pars} pulse_dict = {} pulse_dict.update(mw_pulses_qCP) pulse_dict.update(mw_pulses_qS) pulse_dict.update(swap_qCP) pulse_dict.update(swap_qS) pulse_dict.update(RO_dict) ## End of the getting pulse dict # Preloading should be almost instant (no preloading here) preloaded_kernels_vec = preload_kernels_func(distortion_dict) # renamed as the dict contains the pulse directly # Getting the minus flux pulses should also be in the get pulse dict minus_flux_pulse_pars = deepcopy(flux_pulse_pars_qCP) pulse_dict['mCPhase qCP'] = deepcopy(pulse_dict['CPhase qCP']) pulse_dict['mswap qS'] = deepcopy(pulse_dict['swap qS']) pulse_dict['mCPhase qCP']['amplitude'] = -pulse_dict['CPhase qCP']['amplitude'] pulse_dict['mswap qS']['amplitude'] = -pulse_dict['swap qS']['amplitude'] pulse_dict.update({'mFlux_pulse': minus_flux_pulse_pars}) pulse_dict.update({'dead_time_pulse': {'pulse_type': 'SquarePulse', 'pulse_delay': flux_pulse_pars_qCP['dead_time'], 'channel': flux_pulse_pars_qCP['channel'], 'amplitude': 0, 'length': 0.}}) # Pulse is used to set the starting refpoint for the compensation pulses seq_name = 'swap_CP_swap_2Qubits' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] recovery_swap = deepcopy(pulse_dict['swap qS']) if not CPhase: pulse_dict['CPhase qCP']['amplitude'] = 0 pulse_dict['mCPhase qCP']['amplitude'] = 0 recovery_swap['pulse_delay'] = inter_swap_wait/2 pulse_dict['recovery swap qS'] = recovery_swap pulse_dict['CPhase qCP']['pulse_delay'] = inter_swap_wait/2 # seq has to have at least 2 elts for i, phase in enumerate(phases): if excitations == 'both': if (i < (len(phases)-4*cal_points)/2): excitation = False else: excitation = True elif excitations == 0: excitation = False elif excitations == 1: excitation = True else: raise ValueError( 'excitations {} not recognized'.format(excitations)) if cal_points and (i == (len(phases)-4)): pulse_combinations = ['I qCP', 'I qS', 'RO'] elif cal_points and (i == (len(phases)-3)): pulse_combinations = ['I qCP', 'X180 qS', 'RO'] elif cal_points and ((i == len(phases)-2)): pulse_combinations = ['X180 qCP', 'I qS', 'RO'] elif cal_points and (i == (len(phases)-1)): pulse_combinations = ['X180 qCP', 'X180 qS', 'RO'] else: rphi90_qCP = deepcopy(pulse_dict['X90 qCP']) rphi90_qCP['phase'] = phase pulse_dict['rphi90 qCP'] = rphi90_qCP if excitation: pulse_combinations = ['X180 qS', 'mY90 qCP', 'swap qS'] + \ ['CPhase qCP'] + \ ['recovery swap qS', 'rphi90 qCP', 'X180 qS', 'RO'] + \ ['dead_time_pulse']+['mswap qS']*2+['mCPhase qCP'] else: pulse_combinations = ['I qS', 'mY90 qCP', 'swap qS'] + \ ['CPhase qCP'] + \ ['recovery swap qS', 'rphi90 qCP', 'I qS', 'RO'] + \ ['dead_time_pulse']+['mswap qS']*2+['mCPhase qCP'] # correcting timings pulses = [] for p in pulse_combinations: pulses += [pulse_dict[p]] el = multi_pulse_elt(i, station, pulses) if distortion_dict is not None: el = distort_and_compensate( el, distortion_dict, preloaded_kernels_vec) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq, el_list
def Randomized_Benchmarking_seq(pulse_pars, RO_pars, nr_cliffords, nr_seeds, net_clifford=0, post_msmt_delay=3e-6, cal_points=True, resetless=False, double_curves=False, seq_name=None, verbose=False, upload=True): ''' Input pars: pulse_pars: dict containing pulse pars RO_pars: dict containing RO pars nr_cliffords: list nr_cliffords for which to generate RB seqs nr_seeds: int nr_seeds for which to generate RB seqs net_clifford: int index of net clifford the sequence should perform 0 corresponds to Identity and 3 corresponds to X180 post_msmt_delay: cal_points: bool whether to replace the last two elements with calibration points, set to False if you want to measure a single element (for e.g. optimization) resetless: bool if False will append extra Id element if seq is longer than 50us to ensure proper initialization double_curves: Alternates between net clifford 0 and 3 upload: Upload to the AWG returns: seq, elements_list Conventional use: nr_cliffords = [n1, n2, n3 ....] cal_points = True Optimization use (resetless or not): nr_cliffords = [n] is a list with a single entry cal_points = False net_clifford = 3 (optional) make sure it does a net pi-pulse post_msmt_delay is set (optional) resetless (optional) ''' if seq_name is None: seq_name = 'RandomizedBenchmarking_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) net_cliffords = [0, 3] # Exists purely for the double curves mode i = 0 for seed in range(nr_seeds): for j, n_cl in enumerate(nr_cliffords): if double_curves: net_clifford = net_cliffords[i%2] i += 1 # only used for ensuring unique elt names if cal_points and (j == (len(nr_cliffords)-4) or j == (len(nr_cliffords)-3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (j == (len(nr_cliffords)-2) or j == (len(nr_cliffords)-1)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: cl_seq = rb.randomized_benchmarking_sequence( n_cl, desired_net_cl=net_clifford) pulse_keys = rb.decompose_clifford_seq(cl_seq) pulse_list = [pulses[x] for x in pulse_keys] pulse_list += [RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += post_msmt_delay el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) # If the element is too long, add in an extra wait elt # to skip a trigger if resetless and n_cl*pulse_pars['pulse_delay']*1.875 > 50e-6: el = multi_pulse_elt(i, station, [pulses['I']]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq, el_list else: return seq, el_list
def cos_seq( amplitude, frequency, channels, phases, marker_channels=None, marker_lenght=20e-9, verbose=False, alphas=[1], phi_skews=[0], ): ''' Cosine sequence, plays a continuous cos on the specified channel Input pars: amplitude (float): amplitude in Vpp frequency (float): frequency in Hz channels (list[(str)]: channels on which to set a cos phases (list[(float)]: phases in degree marker_channels (list[(str)]: optionally specify markers to play ''' seq_name = 'ModSquare' seq = sequence.Sequence(seq_name) el_list = [] base_pars = { 'pulse_type': 'ModSquare', 'mod_frequency': frequency, 'length': 2e-6, 'amplitude': amplitude, 'pulse_delay': 0 } marker_pars = { 'pulse_type': 'SquarePulse', 'length': marker_lenght, 'amplitude': 1, 'pulse_delay': 10e-9 } pulse_list = [] for i, phase in enumerate(phases): pulse = deepcopy(base_pars) pulse['I_channel'] = channels[i * 2] pulse['Q_channel'] = channels[i * 2 + 1] pulse['phase'] = phase pulse['alpha'] = alphas[i] pulse['phi_skew'] = phi_skews[i] pulse_list.append(pulse) # copy first element and set extra wait if marker_channels != None: for i, marker_channel in enumerate(marker_channels): pulse = deepcopy(marker_pars) pulse['channel'] = marker_channel if i != 0: pulse['pulse_delay'] = 0 pulse_list.append(pulse) el = multi_pulse_elt(0, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=False) # seq.append_element(el, trigger_wait=False) station.pulsar.program_awgs(seq, *el_list, verbose=verbose) return seq_name
def two_qubit_tomo_cardinal( cardinal, q0_pulse_pars, q1_pulse_pars, RO_pars, timings_dict, verbose=False, upload=True, return_seq=False ): seq_name = "2_qubit_Card_%d_seq" % cardinal seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses q0_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q0_pulse_pars), " q0") q1_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q1_pulse_pars), " q1") RO_dict = {"RO": RO_pars} pulse_dict = {} pulse_dict.update(q0_pulses) pulse_dict.update(q1_pulses) pulse_dict.update(RO_dict) # Timings QQ_buffer = timings_dict["QQ_buffer"] wait_time = timings_dict["wait_time"] msmt_buffer = timings_dict["msmt_buffer"] tomo_list_q0 = ["I q0", "X180 q0", "Y90 q0", "mY90 q0", "X90 q0", "mX90 q0"] tomo_list_q1 = ["I q1", "X180 q1", "Y90 q1", "mY90 q1", "X90 q1", "mX90 q1"] # inner loop on q0 prep_idx_q0 = int(cardinal % 6) prep_idx_q1 = int(((cardinal - prep_idx_q0) / 6) % 6) prep_pulse_q0 = pulse_dict[tomo_list_q0[prep_idx_q0]] prep_pulse_q1 = pulse_dict[tomo_list_q1[prep_idx_q1]] prep_pulse_q1["pulse_delay"] = QQ_buffer + (prep_pulse_q0["sigma"] * prep_pulse_q0["nr_sigma"]) RO_pars["pulse_delay"] += msmt_buffer - (prep_pulse_q1["sigma"] * prep_pulse_q1["nr_sigma"]) # Calibration points cal_points = [ ["I q0", "I q1", "RO"], ["I q0", "I q1", "RO"], ["I q0", "I q1", "RO"], ["I q0", "I q1", "RO"], ["I q0", "I q1", "RO"], ["I q0", "I q1", "RO"], ["I q0", "I q1", "RO"], ["X180 q0", "I q1", "RO"], ["X180 q0", "I q1", "RO"], ["X180 q0", "I q1", "RO"], ["X180 q0", "I q1", "RO"], ["X180 q0", "I q1", "RO"], ["X180 q0", "I q1", "RO"], ["X180 q0", "I q1", "RO"], ["I q0", "X180 q1", "RO"], ["I q0", "X180 q1", "RO"], ["I q0", "X180 q1", "RO"], ["I q0", "X180 q1", "RO"], ["I q0", "X180 q1", "RO"], ["I q0", "X180 q1", "RO"], ["I q0", "X180 q1", "RO"], ["X180 q0", "X180 q1", "RO"], ["X180 q0", "X180 q1", "RO"], ["X180 q0", "X180 q1", "RO"], ["X180 q0", "X180 q1", "RO"], ["X180 q0", "X180 q1", "RO"], ["X180 q0", "X180 q1", "RO"], ["X180 q0", "X180 q1", "RO"], ] for i in range(36): tomo_idx_q0 = int(i % 6) tomo_idx_q1 = int(((i - tomo_idx_q0) / 6) % 6) # print(i,tomo_idx_q0,tomo_idx_q1) tomo_pulse_q0 = pulse_dict[tomo_list_q0[tomo_idx_q0]] tomo_pulse_q1 = pulse_dict[tomo_list_q1[tomo_idx_q1]] tomo_pulse_q0["pulse_delay"] = wait_time + (prep_pulse_q1["sigma"] * prep_pulse_q1["nr_sigma"]) tomo_pulse_q1["pulse_delay"] = QQ_buffer + (tomo_pulse_q0["sigma"] * tomo_pulse_q0["nr_sigma"]) pulse_list = [prep_pulse_q0, prep_pulse_q1, tomo_pulse_q0, tomo_pulse_q1, RO_pars] pulse_list[0]["pulse_delay"] += 0.01e-6 el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) for i, pulse_comb in enumerate(cal_points): pulses = [] for p in pulse_comb: pulses += [pulse_dict[p]] pulses[0]["pulse_delay"] += 0.01e-6 el = multi_pulse_elt(35 + i, station, pulses) el_list.append(el) seq.append_element(el, trigger_wait=True) station.components["AWG"].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def capacity_tomo_seq(bases, states, idle_time, pulse_pars, RO_pars, upload=True, verbose=False): """ input pars bases list of ints: 0 - Z-basis 1 - X-basis 2 - Y-basis states (list of ints): 0 - |0> 1 - |1> idle_time (s) """ assert(len(bases) == len(states)) seq_name = 'Capacity_tomo_seq' seq = sequence.Sequence(seq_name) el_list = [] # Create a dict with the parameters for all the pulses pulse_dict = get_pulse_dict_from_pars(pulse_pars) pulse_dict['I']['pulse_delay'] = idle_time pulse_dict['RO'] = RO_pars pulse_combinations = [['I', 'RO'], ['X180', 'I', 'RO'], ['Y90', 'I', 'mY90', 'RO'], ['mY90', 'I', 'mY90', 'RO'], ['X90', 'I', 'mX90', 'RO'], ['mX90', 'I', 'mX90', 'RO']] # Creates elements containing the primitive pulse sequences for i, pulse_comb in enumerate(pulse_combinations): pulse_list = [] for pulse_key in pulse_comb: pulse_list += [pulse_dict[pulse_key]] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq_idx = [] # Selects the corresponding pulse combination for basis, state in zip(bases, states): if state not in [0, 1]: raise ValueError('state {} not recognized'.format(state)) if basis == 0: # computational(Z)-basis if state == 0: seq_idx += [0] elif state == 1: seq_idx += [1] elif basis == 1: # X basis if state == 0: seq_idx += [2] if state == 1: seq_idx += [3] elif basis == 2: # Y basis if state == 0: seq_idx += [4] if state == 1: seq_idx += [5] else: raise ValueError('basis {} not recognized'.formate(basis)) # Creates a sequence by selecting the right primitive element for i, idx in enumerate(seq_idx): seq.append(name='elt_{}'.format(i), wfname=el_list[idx].name, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq, el_list
def cphase_fringes(phases, q0_pulse_pars, q1_pulse_pars, RO_pars, swap_pars_q0, cphase_pars_q1, timings_dict, distortion_dict, verbose=False, upload=True, return_seq=False): ''' ''' preloaded_kernels_vec = preload_kernels_func(distortion_dict) original_delay = deepcopy(RO_pars)[0]['pulse_delay'] seq_name = 'CPhase' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # print(q0_pulse_pars) q0_pulses = add_suffix_to_dict_keys( get_pulse_dict_from_pars(q0_pulse_pars[0]), ' q0') q1_pulses = add_suffix_to_dict_keys( get_pulse_dict_from_pars(q1_pulse_pars[0]), ' q1') pulse_dict = {} pulse_dict.update(q0_pulses) pulse_dict.update(q1_pulses) pulse_dict.update({'RO': RO_pars[0]}) # print({'RO': RO_pars}) # Timings buffer_mw_flux = timings_dict[0]['buffer_mw_flux'] buffer_flux_mw = timings_dict[0]['buffer_flux_mw'] msmt_buffer = timings_dict[0]['msmt_buffer'] dead_time = timings_dict[0]['dead_time'] # print(buffer_mw_flux,buffer_flux_mw,msmt_buffer,dead_time) # defining main pulses exc_pulse = deepcopy(pulse_dict['X180 q0']) exc_pulse['pulse_delay'] += 0.01e-6 swap_pulse_1 = deepcopy(swap_pars_q0[0]) # print(swap_pulse_1) swap_pulse_1['pulse_delay'] = buffer_mw_flux + \ exc_pulse['sigma']*exc_pulse['nr_sigma'] ramsey_1 = deepcopy(pulse_dict['Y90 q1']) ramsey_1['pulse_delay'] = buffer_flux_mw + swap_pulse_1['length'] cphase_pulse = cphase_pars_q1[0] cphase_amp = cphase_pulse['amplitude'] cphase_pulse['pulse_delay'] = buffer_mw_flux + \ ramsey_1['sigma']*ramsey_1['nr_sigma'] ramsey_2 = deepcopy(pulse_dict['X90 q1']) ramsey_2['pulse_delay'] = buffer_flux_mw + cphase_pulse['length'] swap_pulse_2 = deepcopy(swap_pars_q0[0]) swap_pulse_2['pulse_delay'] = buffer_mw_flux + \ ramsey_2['sigma']*ramsey_2['nr_sigma'] RO_pars[0]['pulse_delay'] = msmt_buffer + swap_pulse_2['length'] # defining compensation pulses swap_comp_1 = deepcopy(swap_pulse_1) swap_pulse_1['pulse_delay'] = RO_pars[0]['length'] + dead_time cphase_comp = deepcopy(cphase_pulse) swap_comp_2 = deepcopy(swap_pulse_2) dead_time_pulse = {'pulse_type': 'SquarePulse', 'pulse_delay': RO_pars[0]['pulse_delay'], 'channel': swap_pars_q0[0]['channel'], 'amplitude': 0, 'length': dead_time} for i, ph2 in enumerate(phases[0]): # print(ph2) ramsey_2['phase'] = ph2 cphase_pulse['amplitude'] = cphase_amp pulse_list = [exc_pulse, swap_pulse_1, ramsey_1, cphase_pulse, ramsey_2, swap_pulse_2, RO_pars[0], swap_comp_1, cphase_comp, swap_comp_2, dead_time_pulse] el = multi_pulse_elt(2*i, station, pulse_list) el_list.append(el) cphase_pulse['amplitude'] = 0. pulse_list = [exc_pulse, swap_pulse_1, ramsey_1, cphase_pulse, ramsey_2, swap_pulse_2, RO_pars[0], swap_comp_1, cphase_comp, swap_comp_2, dead_time_pulse] el = multi_pulse_elt(2*i+1, station, pulse_list) el_list.append(el) # Compensations for i, el in enumerate(el_list): if distortion_dict is not None: el = distort_and_compensate( el, distortion_dict, preloaded_kernels_vec) el_list[i] = el seq.append_element(el, trigger_wait=True) cal_points = 4 RO_pars[0]['pulse_delay'] = original_delay # Calibration points cal_points = [['I q0', 'I q1', 'RO'], ['I q0', 'I q1', 'RO'], ['X180 q0', 'I q1', 'RO'], ['X180 q0', 'I q1', 'RO'], ['I q0', 'X180 q1', 'RO'], ['I q0', 'X180 q1', 'RO'], ['X180 q0', 'X180 q1', 'RO'], ['X180 q0', 'X180 q1', 'RO']] for i, pulse_comb in enumerate(cal_points): pulses = [] for p in pulse_comb: pulses += [pulse_dict[p]] pulses[0]['pulse_delay'] += 0.01e-6 el = multi_pulse_elt(2*len(phases)+i, station, pulses) el_list.append(el) seq.append_element(el, trigger_wait=True) # upload if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def chevron_seq_cphase(lengths, mw_pulse_pars, RO_pars, flux_pulse_pars=None, cphase_pulse_pars=None, artificial_detuning=None, phase_2=None, verbose=False, distortion_dict=None, upload=True, return_seq=False): ''' ''' preloaded_kernels_vec = preload_kernels_func(distortion_dict) if flux_pulse_pars is None: flux_pulse_pars = {'pulse_type': 'SquarePulse', 'pulse_delay': .1e-6, 'channel': 'ch3', 'amplitude': 0.5, 'length': .1e-6} # flux_pulse_pars['amplitude'] = 0. minus_flux_pulse_pars = {'pulse_type': 'SquarePulse', 'pulse_delay': 0., # will be overwritten 'channel': flux_pulse_pars['channel'], 'amplitude': -flux_pulse_pars['amplitude'], 'length': flux_pulse_pars['length']} original_delay = deepcopy(RO_pars)['pulse_delay'] dead_time_pulse = {'pulse_type': 'SquarePulse', 'pulse_delay': (minus_flux_pulse_pars['length']), 'channel': flux_pulse_pars['channel'], 'amplitude': 0, 'length': 0.} seq_name = 'Chevron_seq' minus_cphase_pulse_pars = deepcopy(cphase_pulse_pars) minus_cphase_pulse_pars['amplitude'] = - \ minus_cphase_pulse_pars['amplitude'] seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(mw_pulse_pars) for i, lngt in enumerate(lengths): # seq has to have at least 2 elts cphase_pulse_pars['length'] = lngt minus_cphase_pulse_pars['length'] = lngt cphase_pulse_pars['frequency'] = 0.5/lngt minus_cphase_pulse_pars['frequency'] = 0.5/lngt # cphase_pulse_pars['phase'] = -(90./np.pi)*(cphase_pulse_pars['pulse_delay'])/lngt # minus_cphase_pulse_pars['phase'] = -(90./np.pi)*(minus_cphase_pulse_pars['pulse_delay'])/lngt # correcting timings pulse_buffer = 50e-9 flux_pulse_pars['pulse_delay'] = pulse_buffer + (mw_pulse_pars['sigma'] * mw_pulse_pars['nr_sigma']) msmt_buffer = 50e-9 RO_pars['pulse_delay'] = msmt_buffer + lngt dead_time_pulse['pulse_delay'] = RO_pars['pulse_delay'] dead_time = 3e-6 minus_flux_pulse_pars['pulse_delay'] = dead_time + RO_pars['length'] firstY90m = deepcopy(pulses['Y90']) firstY90m['pulse_delay'] = flux_pulse_pars['length'] + 30e-9 secondY90m = deepcopy(pulses['X90']) if phase_2 is not None: secondY90m['phase'] = phase_2 elif artificial_detuning is not None: secondY90m['phase'] = (lngt-lengths[0]) * artificial_detuning * 360 secondY90m['pulse_delay'] = lngt + 20e-9 pulse_list = [pulses['X180'], flux_pulse_pars, firstY90m, cphase_pulse_pars, secondY90m, RO_pars, minus_flux_pulse_pars, pulses['I'], minus_cphase_pulse_pars, dead_time_pulse] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += 0.01e-6 + ((-int(lngt*1e9)) % 50)*1e-9 el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) for i, el in enumerate(el_list): if distortion_dict is not None: el = distort_and_compensate( el, distortion_dict, preloaded_kernels_vec) el_list[i] = el seq.append_element(el, trigger_wait=True) cal_points = 4 RO_pars['pulse_delay'] = original_delay for i in range(int(cal_points/2)): pulse_list = [pulses['I'], RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += 0.01e-6 el = multi_pulse_elt(len(lengths)+i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) for i in range(int(cal_points/2)): pulse_list = [pulses['X180'], RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += 0.01e-6 el = multi_pulse_elt( len(lengths)+int(cal_points/2)+i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def two_qubit_AllXY(operation_dict, q0='q0', q1='q1', RO_target='all', sequence_type='simultaneous', replace_q1_pulses_X180=False, double_points=True, verbose=False, upload=True, return_seq=False): """ Performs an AllXY sequence on two qubits. Has the option of replacing pulses on q1 with pi pulses Args: operation_dict (dict) : dictionary containing all pulse parameters q0, q1 (str) : target qubits for the sequence RO_target (str) : target for the RO, can be a qubit name or 'all' sequence_type (str) : sequential | interleaved | simultaneous | sandwiched q0|q0|q1|q1 q0|q1|q0|q1 q01|q01 q1|q0|q0|q1 describes the order of the AllXY pulses replace_q1_pulses_X180 (bool) : if True replaces all pulses on q1 with X180 pulses. double_points (bool) : if True measures each point in the AllXY twice verbose (bool) : verbose sequence generation upload (bool) : """ seq_name = 'two_qubit_AllXY_{}_{}'.format(q0, q1) seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] sequencer_config = operation_dict['sequencer_config'] AllXY_pulse_combinations = [['I ', 'I '], ['X180 ', 'X180 '], ['Y180 ', 'Y180 '], ['X180 ', 'Y180 '], ['Y180 ', 'X180 '], ['X90 ', 'I '], ['Y90 ', 'I '], [ 'X90 ', 'Y90 '], ['Y90 ', 'X90 '], ['X90 ', 'Y180 '], [ 'Y90 ', 'X180 '], ['X180 ', 'Y90 '], ['Y180 ', 'X90 '], [ 'X90 ', 'X180 '], ['X180 ', 'X90 '], ['Y90 ', 'Y180 '], [ 'Y180 ', 'Y90 '], ['X180 ', 'I '], ['Y180 ', 'I '], [ 'X90 ', 'X90 '], ['Y90 ', 'Y90 ']] if double_points: AllXY_pulse_combinations = [val for val in AllXY_pulse_combinations for _ in (0, 1)] if sequence_type == 'simultaneous': operation_dict = deepcopy(operation_dict) # prevents overwriting of dict for key in operation_dict.keys(): if q1 in key: operation_dict[key]['refpoint'] = 'start' operation_dict[key]['pulse_delay'] = 0 pulse_list = [] if not replace_q1_pulses_X180: for pulse_comb in AllXY_pulse_combinations: if sequence_type == 'interleaved' or sequence_type == 'simultaneous': pulse_list += [[pulse_comb[0] + q0] + [pulse_comb[0] + q1] + [pulse_comb[1] + q0] + [pulse_comb[1] + q1] + ['RO ' + RO_target]] elif sequence_type == 'sequential': pulse_list += [[pulse_comb[0] + q0] + [pulse_comb[1] + q0] + [pulse_comb[0] + q1] + [pulse_comb[1] + q1] + ['RO ' + RO_target]] elif sequence_type == 'sandwiched': pulse_list += [[pulse_comb[0] + q1] + [pulse_comb[0] + q0] + [pulse_comb[1] + q0] + [pulse_comb[1] + q1] + ['RO ' + RO_target]] else: raise ValueError("sequence_type {} must be in".format(sequence_type) + " ['interleaved', simultaneous', 'sequential', 'sandwiched']") else: for pulse_comb in AllXY_pulse_combinations: if sequence_type == 'interleaved' or sequence_type == 'simultaneous': pulse_list += [[pulse_comb[0] + q0] + ['X180 ' + q1] + [pulse_comb[1] + q0] + ['X180 ' + q1] + ['RO ' + RO_target]] elif sequence_type == 'sequential': pulse_list += [[pulse_comb[0] + q0] + [pulse_comb[1] + q0] + ['X180 ' + q1] + ['X180 ' + q1] + ['RO ' + RO_target]] elif sequence_type == 'sandwiched': pulse_list += [['X180 ' + q1] + [pulse_comb[0] + q0] + [pulse_comb[1] + q0] + ['X180 ' + q1] + ['RO ' + RO_target]] else: raise ValueError("sequence_type {} must be in".format(sequence_type) + " ['interleaved', simultaneous', 'sequential', 'sandwiched']") for i, pulse_comb in enumerate(pulse_list): pulses = [] for p in pulse_comb: pulses += [operation_dict[p]] el = multi_pulse_elt(i, station, pulses, sequencer_config) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def two_qubit_tomo_cardinal(cardinal, q0_pulse_pars, q1_pulse_pars, RO_pars, timings_dict, verbose=False, upload=True, return_seq=False): seq_name = '2_qubit_Card_%d_seq' % cardinal seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses q0_pulses = add_suffix_to_dict_keys( get_pulse_dict_from_pars(q0_pulse_pars), ' q0') q1_pulses = add_suffix_to_dict_keys( get_pulse_dict_from_pars(q1_pulse_pars), ' q1') RO_dict = {'RO': RO_pars} pulse_dict = {} pulse_dict.update(q0_pulses) pulse_dict.update(q1_pulses) pulse_dict.update(RO_dict) # Timings # FIXME: This dictionary should not be required? -MAR # NOTE: required in the CPhase tomo as input but not used QQ_buffer = timings_dict['QQ_buffer'] wait_time = timings_dict['wait_time'] msmt_buffer = timings_dict['msmt_buffer'] tomo_list_q0 = ['I q0', 'X180 q0', 'Y90 q0', 'mY90 q0', 'X90 q0', 'mX90 q0'] tomo_list_q1 = ['I q1', 'X180 q1', 'Y90 q1', 'mY90 q1', 'X90 q1', 'mX90 q1'] # inner loop on q0 prep_idx_q0 = int(cardinal % 6) prep_idx_q1 = int(((cardinal - prep_idx_q0)/6) % 6) prep_pulse_q0 = pulse_dict[tomo_list_q0[prep_idx_q0]] prep_pulse_q1 = pulse_dict[tomo_list_q1[prep_idx_q1]] prep_pulse_q1['pulse_delay'] = QQ_buffer + (prep_pulse_q0['sigma'] * prep_pulse_q0['nr_sigma']) RO_pars['pulse_delay'] += msmt_buffer - (prep_pulse_q1['sigma'] * prep_pulse_q1['nr_sigma']) # Calibration points cal_points = [['I q0', 'I q1', 'RO'], ['I q0', 'I q1', 'RO'], ['I q0', 'I q1', 'RO'], ['I q0', 'I q1', 'RO'], ['I q0', 'I q1', 'RO'], ['I q0', 'I q1', 'RO'], ['I q0', 'I q1', 'RO'], ['X180 q0', 'I q1', 'RO'], ['X180 q0', 'I q1', 'RO'], ['X180 q0', 'I q1', 'RO'], ['X180 q0', 'I q1', 'RO'], ['X180 q0', 'I q1', 'RO'], ['X180 q0', 'I q1', 'RO'], ['X180 q0', 'I q1', 'RO'], ['I q0', 'X180 q1', 'RO'], ['I q0', 'X180 q1', 'RO'], ['I q0', 'X180 q1', 'RO'], ['I q0', 'X180 q1', 'RO'], ['I q0', 'X180 q1', 'RO'], ['I q0', 'X180 q1', 'RO'], ['I q0', 'X180 q1', 'RO'], ['X180 q0', 'X180 q1', 'RO'], ['X180 q0', 'X180 q1', 'RO'], ['X180 q0', 'X180 q1', 'RO'], ['X180 q0', 'X180 q1', 'RO'], ['X180 q0', 'X180 q1', 'RO'], ['X180 q0', 'X180 q1', 'RO'], ['X180 q0', 'X180 q1', 'RO']] for i in range(36): tomo_idx_q0 = int(i % 6) tomo_idx_q1 = int(((i - tomo_idx_q0)/6) % 6) # print(i,tomo_idx_q0,tomo_idx_q1) tomo_pulse_q0 = pulse_dict[tomo_list_q0[tomo_idx_q0]] tomo_pulse_q1 = pulse_dict[tomo_list_q1[tomo_idx_q1]] tomo_pulse_q0['pulse_delay'] = wait_time + (prep_pulse_q1['sigma'] * prep_pulse_q1['nr_sigma']) tomo_pulse_q1['pulse_delay'] = QQ_buffer + (tomo_pulse_q0['sigma'] * tomo_pulse_q0['nr_sigma']) pulse_list = [prep_pulse_q0, prep_pulse_q1, tomo_pulse_q0, tomo_pulse_q1, RO_pars] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) for i, pulse_comb in enumerate(cal_points): pulses = [] for p in pulse_comb: pulses += [pulse_dict[p]] el = multi_pulse_elt(35+i, station, pulses) el_list.append(el) seq.append_element(el, trigger_wait=True) station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def CPMG_seq(times, pulse_pars, CPMG_order, RO_pars, artificial_detuning=None, cal_points=True, verbose=False, upload=True, return_seq=False): ''' Echo sequence for a single qubit using the tektronix. Input pars: times: array of times between (start of) pulses (s) CPMG_order: Number of refocussing Y180 pulses artificial_detuning: artificial_detuning (Hz) implemented using phase pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters cal_points: whether to use calibration points or not ''' seq_name = 'CPMG_sequence' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) CPMG_list = [] for tt in range(CPMG_order): CPMG_list.append(deepcopy(pulses['Y180'])) #Start this pulse 'tau/N' or 'tau/2N' since the END of the previous pulse CPMG_list[tt]['refpoint'] = 'end' final_X90 = deepcopy(pulses['X90']) final_X90['refpoint'] = 'end' starting_X90 = deepcopy(pulses['X90']) #This one can start from the start of the trigger pulse starting_X90['refpoint'] = 'start' for i, tau in enumerate(times): CPMG_list[0]['pulse_delay'] = tau / (2 * CPMG_order) for tt in range(1, CPMG_order): CPMG_list[tt]['pulse_delay'] = tau / CPMG_order final_X90['pulse_delay'] = tau / (2 * CPMG_order) if artificial_detuning is not None: final_X90['phase'] = (tau - times[0]) * artificial_detuning * 360 if cal_points and (i == (len(times) - 4) or i == (len(times) - 3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(times) - 2) or i == (len(times) - 1)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: pulse_list = [starting_X90] pulse_list += CPMG_list pulse_list += [final_X90] pulse_list += [RO_pars] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def chevron_seq(mw_pulse_pars, RO_pars, flux_pulse_pars, pulse_lengths=np.arange(0, 120e-9, 2e-9), verbose=False, distortion_dict=None, upload=True, cal_points=True): ''' Chevron sequence where length of the "swap" operation is varied X180 - swap(l) - RO mw_pulse_pars: (dict) qubit control pulse pars RO_pars: (dict) qubit RO pars flux_pulse_pars: (dict) flux puplse pars nr_pulses_list (list) nr of swaps gates for each element verbose=False: (bool) used for verbosity printing in the pulsar distortion_dict=None: (dict) flux_pulse predistortion kernels upload=True: (bool) uploads to AWG, set False for testing purposes cal_points=True: (bool) wether to use calibration points ''' preloaded_kernels_vec = preload_kernels_func(distortion_dict) # renamed as the dict contains the pulse directly minus_flux_pulse_pars = deepcopy(flux_pulse_pars) minus_flux_pulse_pars['amplitude'] = -flux_pulse_pars['amplitude'] # Pulse is used to set the starting refpoint for the compensation pulses dead_time_pulse_pars = {'pulse_type': 'SquarePulse', 'pulse_delay': flux_pulse_pars['dead_time'], 'channel': flux_pulse_pars['channel'], 'amplitude': 0, 'length': 0.} seq_name = 'Chevron_seq' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(mw_pulse_pars) # seq has to have at least 2 elts for i, pulse_length in enumerate(pulse_lengths): if cal_points and (i == (len(pulse_lengths)-4) or i == (len(pulse_lengths)-3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (i == (len(pulse_lengths)-2) or i == (len(pulse_lengths)-1)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: flux_pulse_pars['square_pulse_length'] = pulse_length minus_flux_pulse_pars['square_pulse_length'] = pulse_length pulse_list = [pulses['X180']] + [flux_pulse_pars]+[RO_pars] + \ [dead_time_pulse_pars] + [minus_flux_pulse_pars] el = multi_pulse_elt(i, station, pulse_list) if distortion_dict is not None: el = distort_and_compensate( el, distortion_dict, preloaded_kernels_vec) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) return seq, el_list
def cphase_fringes( phases, q0_pulse_pars, q1_pulse_pars, RO_pars, swap_pars_q0, cphase_pars_q1, timings_dict, distortion_dict, verbose=False, upload=True, return_seq=False, ): """ """ preloaded_kernels_vec = preload_kernels_func(distortion_dict) original_delay = deepcopy(RO_pars)[0]["pulse_delay"] seq_name = "CPhase" seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # print(q0_pulse_pars) q0_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q0_pulse_pars[0]), " q0") q1_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q1_pulse_pars[0]), " q1") pulse_dict = {} pulse_dict.update(q0_pulses) pulse_dict.update(q1_pulses) pulse_dict.update({"RO": RO_pars[0]}) # print({'RO': RO_pars}) # Timings buffer_mw_flux = timings_dict[0]["buffer_mw_flux"] buffer_flux_mw = timings_dict[0]["buffer_flux_mw"] msmt_buffer = timings_dict[0]["msmt_buffer"] dead_time = timings_dict[0]["dead_time"] # print(buffer_mw_flux,buffer_flux_mw,msmt_buffer,dead_time) # defining main pulses exc_pulse = deepcopy(pulse_dict["X180 q0"]) exc_pulse["pulse_delay"] += 0.01e-6 swap_pulse_1 = deepcopy(swap_pars_q0[0]) # print(swap_pulse_1) swap_pulse_1["pulse_delay"] = buffer_mw_flux + exc_pulse["sigma"] * exc_pulse["nr_sigma"] ramsey_1 = deepcopy(pulse_dict["Y90 q1"]) ramsey_1["pulse_delay"] = buffer_flux_mw + swap_pulse_1["length"] cphase_pulse = cphase_pars_q1[0] cphase_amp = cphase_pulse["amplitude"] cphase_pulse["pulse_delay"] = buffer_mw_flux + ramsey_1["sigma"] * ramsey_1["nr_sigma"] ramsey_2 = deepcopy(pulse_dict["X90 q1"]) ramsey_2["pulse_delay"] = buffer_flux_mw + cphase_pulse["length"] swap_pulse_2 = deepcopy(swap_pars_q0[0]) swap_pulse_2["pulse_delay"] = buffer_mw_flux + ramsey_2["sigma"] * ramsey_2["nr_sigma"] RO_pars[0]["pulse_delay"] = msmt_buffer + swap_pulse_2["length"] # defining compensation pulses swap_comp_1 = deepcopy(swap_pulse_1) swap_pulse_1["pulse_delay"] = RO_pars[0]["length"] + dead_time cphase_comp = deepcopy(cphase_pulse) swap_comp_2 = deepcopy(swap_pulse_2) dead_time_pulse = { "pulse_type": "SquarePulse", "pulse_delay": RO_pars[0]["pulse_delay"], "channel": swap_pars_q0[0]["channel"], "amplitude": 0, "length": dead_time, } for i, ph2 in enumerate(phases[0]): # print(ph2) ramsey_2["phase"] = ph2 cphase_pulse["amplitude"] = cphase_amp pulse_list = [ exc_pulse, swap_pulse_1, ramsey_1, cphase_pulse, ramsey_2, swap_pulse_2, RO_pars[0], swap_comp_1, cphase_comp, swap_comp_2, dead_time_pulse, ] el = multi_pulse_elt(2 * i, station, pulse_list) el_list.append(el) cphase_pulse["amplitude"] = 0.0 pulse_list = [ exc_pulse, swap_pulse_1, ramsey_1, cphase_pulse, ramsey_2, swap_pulse_2, RO_pars[0], swap_comp_1, cphase_comp, swap_comp_2, dead_time_pulse, ] el = multi_pulse_elt(2 * i + 1, station, pulse_list) el_list.append(el) # Compensations for i, el in enumerate(el_list): if distortion_dict is not None: el = distort_and_compensate(el, distortion_dict, preloaded_kernels_vec) el_list[i] = el seq.append_element(el, trigger_wait=True) cal_points = 4 RO_pars[0]["pulse_delay"] = original_delay # Calibration points cal_points = [ ["I q0", "I q1", "RO"], ["I q0", "I q1", "RO"], ["X180 q0", "I q1", "RO"], ["X180 q0", "I q1", "RO"], ["I q0", "X180 q1", "RO"], ["I q0", "X180 q1", "RO"], ["X180 q0", "X180 q1", "RO"], ["X180 q0", "X180 q1", "RO"], ] for i, pulse_comb in enumerate(cal_points): pulses = [] for p in pulse_comb: pulses += [pulse_dict[p]] pulses[0]["pulse_delay"] += 0.01e-6 el = multi_pulse_elt(2 * len(phases) + i, station, pulses) el_list.append(el) seq.append_element(el, trigger_wait=True) # upload if upload: station.components["AWG"].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def single_pulse_seq(pulse_pars=None, comp_pulse=True, verbose=False, distortion_dict=None, return_seq=False): ''' ''' if pulse_pars is None: pulse_pars = {'pulse_type': 'SquarePulse', 'pulse_delay': .1e-6, 'channel': 'ch3', 'amplitude': 0.5, 'length': .1e-6, 'dead_time_length': 10e-6} minus_pulse_pars = {'pulse_type': 'SquarePulse', 'pulse_delay': 3e-6 + pulse_pars['length'] + pulse_pars['pulse_delay'], 'channel': pulse_pars['channel'], 'amplitude': -pulse_pars['amplitude'], 'length': pulse_pars['length'], 'dead_time_length': 10e-6} dead_time_pulse = {'pulse_type': 'SquarePulse', 'pulse_delay': (minus_pulse_pars['length']), 'channel': pulse_pars['channel'], 'amplitude': 0, 'length': pulse_pars['dead_time_length']} trig_marker = {'pulse_type': 'SquarePulse', 'pulse_delay': 0., 'channel': 'ch1_marker1', 'amplitude': 1., 'length': .1e-6} # 'length': 5e-6} seq_name = 'Square_seq' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] for i, iter in enumerate([0, 1]): # seq has to have at least 2 elts if comp_pulse: pulse_list = [ pulse_pars, trig_marker, minus_pulse_pars, dead_time_pulse] else: pulse_list = [pulse_pars, trig_marker, dead_time_pulse] # pulse_list = [pulse_pars, dead_time_pulse] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) if distortion_dict is not None: preloaded_kernels_vec = preload_kernels_func(distortion_dict) else: preloaded_kernels = [] for i, el in enumerate(el_list): if distortion_dict is not None: el = distort_and_compensate( el, distortion_dict, preloaded_kernels_vec) el_list[i] = el seq.append_element(el, trigger_wait=True) station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def two_qubit_tomo_cphase_cardinal(cardinal_state, operation_dict, qS, qCZ, RO_target, distortion_dict, CZ_disabled=False, cal_points_with_flux_pulses=True, verbose=False, upload=True): ''' qS is swap qubit qCZ is cphase qubit ''' sequencer_config = operation_dict['sequencer_config'] seq_name = '2_qubit_CPhase_Cardinal_Tomo_%d_seq' % cardinal_state seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] tomo_list_qS = [] tomo_list_qCZ = [] # Tomo pulses span a basis covering all the cardinal points tomo_pulses = ['I ', 'X180 ', 'Y90 ', 'mY90 ', 'X90 ', 'mX90 '] for tp in tomo_pulses: tomo_list_qS += [tp+qS] tomo_list_qCZ += [tp+qCZ] ########################### # Defining sub sequences # ########################### # This forms the base sequence, note that gate1, gate2 and after_pulse will # be replaced to prepare the desired state and tomo1 and tomo2 will be # replaced with tomography pulses base_sequence = ( ['gate1 ' + qS, 'gate2 ' + qCZ, 'SWAP '+qS, 'CZ ' + qCZ, 'rSWAP ' + qS, 'SWAP_corr ' + qS, 'CZ_corr ' + qCZ, 'after_pulse ' + qCZ, 'tomo1 '+qCZ, 'tomo2 '+qS, 'RO '+RO_target]) # Calibration points # every calibration point is repeated 7 times to have 64 elts in total cal_points = [['I '+qCZ, 'I '+qS, 'RO '+RO_target]]*7 +\ [['I '+qCZ, 'X180 '+qS, 'RO '+RO_target]]*7 +\ [['X180 '+qCZ, 'I '+qS, 'RO '+RO_target]]*7 +\ [['X180 '+qCZ, 'X180 '+qS, 'RO '+RO_target]]*7 if CZ_disabled: operation_dict['CZ '+qCZ]['amplitude'] = 0 operation_dict['CZ '+qCZ]['phase_corr_pulse_amp'] = 0 ################################################ # Creating additional pulses for this sequence # ################################################ # the recovery SWAP is identical to the regular SWAP operation, unless # an rSWAP is explicitly contained in the operation dict if ('rSWAP ' + qS) not in operation_dict.keys(): operation_dict['rSWAP ' + qS] = deepcopy(operation_dict['SWAP ' + qS]) operation_dict['CZ_corr ' + qCZ]['refpoint'] = 'simultaneous' ################ # cardinal states # ################ # here select the qubit gates (depending on cardinal_state) prep_idx_qS = int(cardinal_state % 6) prep_idx_qCZ = int(((cardinal_state - prep_idx_qS)/6) % 6) print('Compensation qCP {:.3f}'.format( operation_dict['CZ_corr ' + qCZ]['amplitude'])) print('Compensation qS {:.3f}'.format( operation_dict['SWAP_corr ' + qS]['amplitude'])) ######################################################## # Here the actual pulses of all elements get defined # ######################################################## # We start by replacing the state prepartion pulses base_sequence[0] = tomo_list_qS[prep_idx_qS] base_sequence[1] = tomo_list_qCZ[prep_idx_qCZ] base_sequence[7] = 'I ' + qCZ seq_pulse_list = [] for i in range(36): tomo_idx_qS = int(i % 6) tomo_idx_qCZ = int(((i - tomo_idx_qS)/6) % 6) base_sequence[8] = tomo_list_qCZ[tomo_idx_qCZ] base_sequence[9] = tomo_list_qS[tomo_idx_qS] seq_pulse_list += [deepcopy(base_sequence)] print(len(cal_points)) for cal_pulses in cal_points: if cal_points_with_flux_pulses: base_sequence[0] = 'I ' + qS base_sequence[1] = 'I ' + qCZ base_sequence[7] = 'I ' + qCZ base_sequence[-3:] = cal_pulses seq_pulse_list += [deepcopy(base_sequence)] else: seq_pulse_list += [cal_pulses] for i, pulse_list in enumerate(seq_pulse_list): pulses = [] for p in pulse_list: pulses += [operation_dict[p]] el = multi_pulse_elt(i, station, pulses, sequencer_config) if distortion_dict is not None: print('\rDistorting element {}/{} '.format(i+1, len(seq_pulse_list)), end='') el = distort_and_compensate( el, distortion_dict) el_list.append(el) seq.append_element(el, trigger_wait=True) station.pulsar.program_awgs(seq, *el_list, verbose=verbose) return seq, el_list
def XSWAPxy(phis, mw_pulse_pars, RO_pars, flux_pulse_pars=None, excite=True, verbose=False, distortion_dict=None, upload=True, return_seq=False): ''' ''' preloaded_kernels_vec = preload_kernels_func(distortion_dict) if flux_pulse_pars is None: flux_pulse_pars = {'pulse_type': 'SquarePulse', 'pulse_delay': .1e-6, 'channel': 'ch3', 'amplitude': 0.5, 'length': .1e-6} # flux_pulse_pars['amplitude'] = 0. minus_flux_pulse_pars = {'pulse_type': 'SquarePulse', 'pulse_delay': 0., # will be overwritten 'channel': flux_pulse_pars['channel'], 'amplitude': -flux_pulse_pars['amplitude'], 'length': flux_pulse_pars['length']} original_delay = deepcopy(RO_pars)['pulse_delay'] dead_time_pulse = {'pulse_type': 'SquarePulse', 'pulse_delay': (minus_flux_pulse_pars['length']), 'channel': flux_pulse_pars['channel'], 'amplitude': 0, 'length': 0.} seq_name = 'Chevron_seq' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(mw_pulse_pars) lngt = flux_pulse_pars['length'] minus_flux_pulse_pars['length'] = lngt for i in range(rep_max): # seq has to have at least 2 elts # correcting timings pulse_buffer = 50e-9 flux_pulse_pars['pulse_delay'] = pulse_buffer + (mw_pulse_pars['sigma'] * mw_pulse_pars['nr_sigma']) msmt_buffer = 50e-9 RO_pars['pulse_delay'] = msmt_buffer + lngt dead_time_pulse['pulse_delay'] = RO_pars['pulse_delay'] dead_time = 3e-6 minus_flux_pulse_pars['pulse_delay'] = dead_time + RO_pars['length'] if excite: init_pulse = pulses['X180'] else: init_pulse = pulses['I'] buffer_swap = 50e-9 sec_flux_pulse_pars = deepcopy(flux_pulse_pars) flux_pulse_pars['pulse_delay'] = flux_pulse_pars[ 'length'] + buffer_swap sec_minus_flux_pulse_pars = deepcopy(minus_flux_pulse_pars) sec_minus_flux_pulse_pars['pulse_delay'] = minus_flux_pulse_pars[ 'length'] + buffer_swap if i == 0: pulse_list = [init_pulse, flux_pulse_pars, RO_pars, minus_flux_pulse_pars, dead_time_pulse] else: pulse_list = [init_pulse, flux_pulse_pars] + [sec_flux_pulse_pars]*(2*i) + [RO_pars, minus_flux_pulse_pars] + [sec_minus_flux_pulse_pars]*(2*i) + [dead_time_pulse] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) # + ((-int(lngt*1e9)) % 50)*1e-9 pulse_list[0]['pulse_delay'] += 0.01e-6 el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) for i, el in enumerate(el_list): if distortion_dict is not None: el = distort_and_compensate( el, distortion_dict, preloaded_kernels_vec) el_list[i] = el seq.append_element(el, trigger_wait=True) cal_points = 4 RO_pars['pulse_delay'] = original_delay for i in range(int(cal_points/2)): pulse_list = [pulses['I'], RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += 0.01e-6 el = multi_pulse_elt(len(np.arange(rep_max))+i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) for i in range(int(cal_points/2)): pulse_list = [pulses['X180'], RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += 0.01e-6 el = multi_pulse_elt( len(np.arange(rep_max))+int(cal_points/2)+i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def T1_qp_seq(times, pulse_pars, RO_pars, N_pi_pulses, N_pi_pulse_delay, cal_points=True, verbose=False, upload=True, return_seq=True): ''' Rabi sequence for a single qubit using the tektronix. SSB_Drag pulse is used for driving, simple modualtion used for RO Input pars: times: array of times to wait after the initial pi-pulse pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters ''' seq_name = 'T1_Quasiparticle_sequence' seq = sequence.Sequence(seq_name) el_list = [] RO_pulse_delay = RO_pars['pulse_delay'] RO_pars = deepcopy(RO_pars) # Prevents overwriting of the dict pulses = get_pulse_dict_from_pars(pulse_pars) # for every different tau: # make N pi pulses # append the T1 experiment # make an element out of the above sequence # send to the AWG starting_X180 = deepcopy(pulses['X180']) starting_X180['refpoint'] = 'start' QP_X180_list = [] for tt in range(N_pi_pulses - 1): QP_X180_list.append(deepcopy(pulses['X180'])) #Add a delay of N_2pi_pulse_delay counting from the start of the #previous pumping pulse QP_X180_list[tt]['refpoint'] = 'start' QP_X180_list[tt]['pulse_delay'] = N_pi_pulse_delay T1_X180 = deepcopy(pulses['X180']) T1_X180['refpoint'] = 'start' T1_X180['pulse_delay'] = N_pi_pulse_delay for i, tau in enumerate(times): # seq has to have at least 2 elts RO_pars[ 'pulse_delay'] = RO_pulse_delay + tau #Time of gate + free evolution time RO_pars['refpoint'] = 'start' # time defined between start of ops if (cal_points and (i == (len(times) - 4) or i == (len(times) - 3))): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif (cal_points and (i == (len(times) - 2) or i == (len(times) - 1))): RO_pars['pulse_delay'] = RO_pulse_delay el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: # el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) pulse_list = [starting_X180] pulse_list += QP_X180_list pulse_list += [T1_X180] pulse_list += [RO_pars] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def BusEcho(times, mw_pulse_pars, RO_pars, artificial_detuning=None, flux_pulse_pars=None, verbose=False, distortion_dict=None, upload=True, return_seq=False): ''' ''' preloaded_kernels_vec = preload_kernels_func(distortion_dict) if flux_pulse_pars is None: raise ValueError('Need flux parameters for the gate.') minus_flux_pulse_pars = deepcopy(flux_pulse_pars) minus_flux_pulse_pars['amplitude'] = -minus_flux_pulse_pars['amplitude'] original_delay = deepcopy(RO_pars)['pulse_delay'] seq_name = 'BusEcho_seq' seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] pulses = get_pulse_dict_from_pars(mw_pulse_pars) pulse_pars_x2 = deepcopy(pulses['X90']) dead_time_pulse = {'pulse_type': 'SquarePulse', 'pulse_delay': (minus_flux_pulse_pars['length']), 'channel': flux_pulse_pars['channel'], 'amplitude': 0, 'length': 0.} for i, tt in enumerate(times): # correcting timings pulse_buffer = 50e-9 flux_pulse_pars['pulse_delay'] = pulse_buffer + (mw_pulse_pars['sigma'] * mw_pulse_pars['nr_sigma']) flux_pulse_pars_2 = deepcopy(flux_pulse_pars) # flux_pulse_pars_2['amplitude'] = 0. flux_pulse_pars_2['pulse_delay'] = tt*0.5 + flux_pulse_pars['length'] msmt_buffer = 50e-9 RO_pars['pulse_delay'] = msmt_buffer + flux_pulse_pars['length'] dead_time = 3e-6 minus_flux_pulse_pars['pulse_delay'] = dead_time + RO_pars['length'] minus_flux_pulse_pars_2 = deepcopy(flux_pulse_pars_2) minus_flux_pulse_pars_2['amplitude'] = - \ minus_flux_pulse_pars_2['amplitude'] dead_time_pulse['pulse_delay'] = RO_pars['pulse_delay'] if artificial_detuning is not None: pulse_pars_x2['phase'] = (tt-times[0]) * artificial_detuning * 360 pulse_list = [pulses['Y90'], flux_pulse_pars, flux_pulse_pars_2, pulses['X180'], flux_pulse_pars, flux_pulse_pars_2, pulse_pars_x2, RO_pars, minus_flux_pulse_pars, minus_flux_pulse_pars_2, pulses[ 'I'], minus_flux_pulse_pars, minus_flux_pulse_pars_2, dead_time_pulse] # This ensures fixed point pulse_list[0]['pulse_delay'] += 0.01e-6 # + ((-int(tt*1e9)) % 50)*1e-9 el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) for i, el in enumerate(el_list): if distortion_dict is not None: el = distort_and_compensate( el, distortion_dict, preloaded_kernels_vec) el_list[i] = el seq.append_element(el, trigger_wait=True) cal_points = 4 RO_pars['pulse_delay'] = original_delay for i in range(int(cal_points/2)): pulse_list = [pulses['I'], RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += 0.01e-6 el = multi_pulse_elt(len(times)+i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) for i in range(int(cal_points/2)): pulse_list = [pulses['X180'], RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += 0.01e-6 el = multi_pulse_elt( len(times)+int(cal_points/2)+i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.components['AWG'].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq
def Randomized_Benchmarking_seq(pulse_pars, RO_pars, nr_cliffords, nr_seeds, net_clifford=0, post_msmt_delay=3e-6, cal_points=True, resetless=False, double_curves=False, seq_name=None, verbose=False, upload=True): ''' Input pars: pulse_pars: dict containing pulse pars RO_pars: dict containing RO pars nr_cliffords: list nr_cliffords for which to generate RB seqs nr_seeds: int nr_seeds for which to generate RB seqs net_clifford: int index of net clifford the sequence should perform 0 corresponds to Identity and 3 corresponds to X180 post_msmt_delay: cal_points: bool whether to replace the last two elements with calibration points, set to False if you want to measure a single element (for e.g. optimization) resetless: bool if False will append extra Id element if seq is longer than 50us to ensure proper initialization double_curves: Alternates between net clifford 0 and 3 upload: Upload to the AWG returns: seq, elements_list Conventional use: nr_cliffords = [n1, n2, n3 ....] cal_points = True Optimization use (resetless or not): nr_cliffords = [n] is a list with a single entry cal_points = False net_clifford = 3 (optional) make sure it does a net pi-pulse post_msmt_delay is set (optional) resetless (optional) ''' if seq_name is None: seq_name = 'RandomizedBenchmarking_sequence' seq = sequence.Sequence(seq_name) el_list = [] pulses = get_pulse_dict_from_pars(pulse_pars) net_cliffords = [0, 3] # Exists purely for the double curves mode i = 0 for seed in range(nr_seeds): for j, n_cl in enumerate(nr_cliffords): if double_curves: net_clifford = net_cliffords[i % 2] i += 1 # only used for ensuring unique elt names if cal_points and (j == (len(nr_cliffords) - 4) or j == (len(nr_cliffords) - 3)): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif cal_points and (j == (len(nr_cliffords) - 2) or j == (len(nr_cliffords) - 1)): el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: cl_seq = rb.randomized_benchmarking_sequence( n_cl, desired_net_cl=net_clifford) pulse_keys = rb.decompose_clifford_seq(cl_seq) pulse_list = [pulses[x] for x in pulse_keys] pulse_list += [RO_pars] # copy first element and set extra wait pulse_list[0] = deepcopy(pulse_list[0]) pulse_list[0]['pulse_delay'] += post_msmt_delay el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) # If the element is too long, add in an extra wait elt # to skip a trigger if resetless and n_cl * pulse_pars['pulse_delay'] * 1.875 > 50e-6: el = multi_pulse_elt(i, station, [pulses['I']]) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) return seq, el_list else: return seq, el_list
def T1_2pi_qp_seq(times, pulse_pars, RO_pars, N_2pi_pulses, N_2pi_pulse_delay, cal_points=True, verbose=False, upload=True, return_seq=True): ''' for every different tau: make N pi pulses append the T1 experiment make an element out of the above sequence send to the AWG ''' seq_name = 'T1_2pi_Quasiparticle_sequence' seq = sequence.Sequence(seq_name) el_list = [] RO_pulse_delay = RO_pars['pulse_delay'] RO_pars = deepcopy(RO_pars) # Prevents overwriting of the dict pulses = get_pulse_dict_from_pars(pulse_pars) #First 2pi pulse starting_X360 = deepcopy(pulses['X360']) starting_X360['refpoint'] = 'start' QP_X360_list = [] #Add N-1 extra 2pi pulses for tt in range(N_2pi_pulses - 1): QP_X360_list.append(deepcopy(pulses['X360'])) #Add a delay of N_2pi_pulse_delay counting from the start of the #previous pumping pulse QP_X360_list[tt]['refpoint'] = 'start' QP_X360_list[tt]['pulse_delay'] = N_2pi_pulse_delay #Add a pi probe pulse T1_X180 = deepcopy(pulses['X180']) T1_X180['refpoint'] = 'start' T1_X180['pulse_delay'] = N_2pi_pulse_delay for i, tau in enumerate(times): # seq has to have at least 2 elts RO_pars['pulse_delay'] = RO_pulse_delay + tau RO_pars['refpoint'] = 'start' # time defined between start of ops if (cal_points and (i == (len(times) - 4) or i == (len(times) - 3))): el = multi_pulse_elt(i, station, [pulses['I'], RO_pars]) elif (cal_points and (i == (len(times) - 2) or i == (len(times) - 1))): RO_pars['pulse_delay'] = RO_pulse_delay el = multi_pulse_elt(i, station, [pulses['X180'], RO_pars]) else: pulse_list = [starting_X360] pulse_list += QP_X360_list pulse_list += [T1_X180] pulse_list += [RO_pars] el = multi_pulse_elt(i, station, pulse_list) el_list.append(el) seq.append_element(el, trigger_wait=True) if upload: station.pulsar.program_awgs(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name
def two_qubit_AllXY( q0_pulse_pars, q1_pulse_pars, RO_pars, double_points=True, verbose=False, upload=True, return_seq=False ): """ Performs an AllXY on the first qubit will doing a pi-pulse before and after the AllXY on the second qubit AllXY q0 - RO X180 q1 - AllXY q0 - X180 q1 - RO """ seq_name = "2_qubit_AllXY_sequence" seq = sequence.Sequence(seq_name) station.pulsar.update_channel_settings() el_list = [] # Create a dict with the parameters for all the pulses q0_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q0_pulse_pars), " q0") q1_pulses = add_suffix_to_dict_keys(get_pulse_dict_from_pars(q1_pulse_pars), " q1") RO_dict = {"RO": RO_pars} pulse_dict = {} pulse_dict.update(q0_pulses) pulse_dict.update(q1_pulses) pulse_dict.update(RO_dict) AllXY_pulse_combinations = [ ["I q0", "I q0"], ["X180 q0", "X180 q0"], ["Y180 q0", "Y180 q0"], ["X180 q0", "Y180 q0"], ["Y180 q0", "X180 q0"], ["X90 q0", "I q0"], ["Y90 q0", "I q0"], ["X90 q0", "Y90 q0"], ["Y90 q0", "X90 q0"], ["X90 q0", "Y180 q0"], ["Y90 q0", "X180 q0"], ["X180 q0", "Y90 q0"], ["Y180 q0", "X90 q0"], ["X90 q0", "X180 q0"], ["X180 q0", "X90 q0"], ["Y90 q0", "Y180 q0"], ["Y180 q0", "Y90 q0"], ["X180 q0", "I q0"], ["Y180 q0", "I q0"], ["X90 q0", "X90 q0"], ["Y90 q0", "Y90 q0"], ] if double_points: AllXY_pulse_combinations = [val for val in AllXY_pulse_combinations for _ in (0, 1)] pulse_list = [] for pulse_comb in AllXY_pulse_combinations: pulse_list += [pulse_comb + ["RO"]] for pulse_comb in AllXY_pulse_combinations: pulse_list += [["X180 q1"] + pulse_comb + ["X180 q1", "RO"]] for i, pulse_comb in enumerate(pulse_list): pulses = [] for p in pulse_comb: pulses += [pulse_dict[p]] el = multi_pulse_elt(i, station, pulses) el_list.append(el) seq.append_element(el, trigger_wait=True) station.components["AWG"].stop() station.pulsar.program_awg(seq, *el_list, verbose=verbose) if return_seq: return seq, el_list else: return seq_name