def randomized_benchmarking(qubit_name, nr_cliffords, nr_seeds, net_clifford=0, restless=False, label='randomized_benchmarking', cal_points=True, double_curves=True): ''' Input 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 restless: bool, does not initialize if restless is True label: some string that can be used as a label. 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) double_curves: Alternates between net clifford 0 and 3 returns: qasm_file generates a qasm file for single qubit Clifford based randomized benchmarking. ''' net_cliffords = [0, 3] # Exists purely for the double curves mode filename = join(base_qasm_path, label+'.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) i = 0 for seed in range(nr_seeds): for j, n_cl in enumerate(nr_cliffords): if not restless: qasm_file.writelines('init_all \n') if cal_points and (j == (len(nr_cliffords)-4) or j == (len(nr_cliffords)-3)): qasm_file.writelines('RO {} \n'.format(qubit_name)) elif cal_points and (j == (len(nr_cliffords)-2) or j == (len(nr_cliffords)-1)): qasm_file.writelines('X180 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) else: if double_curves: net_clifford = net_cliffords[i % 2] i += 1 cl_seq = rb.randomized_benchmarking_sequence( n_cl, desired_net_cl=net_clifford) pulse_keys = rb.decompose_clifford_seq(cl_seq) for pulse in pulse_keys: if pulse != 'I': qasm_file.writelines('{} {}\n'.format( pulse, qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def rb_block(self, sp1d_idx, sp2d_idx, **kw): """ Creates simultaneous blocks of RB pulses for each task in preprocessed_task_list. Args: sp1d_idx (int): current iteration index in the 1D sweep points array sp2d_idx (int): current iteration index in the 2D sweep points array Keyword args: interleaved_gate (see docstring of parent class) """ interleaved_gate = kw.get('interleaved_gate', None) pulse_op_codes_list = [] tl = [self.preprocessed_task_list[0]] if self.identical_pulses else \ self.preprocessed_task_list for i, task in enumerate(tl): param_name = 'seeds' if interleaved_gate is None else 'seeds_irb' seed_idx = sp1d_idx if self.sweep_type['seeds'] == 0 else sp2d_idx clf_idx = sp1d_idx if self.sweep_type[ 'cliffords'] == 0 else sp2d_idx seed = task['sweep_points'].get_sweep_params_property( 'values', self.sweep_type['seeds'], param_name)[seed_idx, clf_idx] clifford = task['sweep_points'].get_sweep_params_property( 'values', self.sweep_type['cliffords'], 'cliffords')[clf_idx] cl_seq = rb.randomized_benchmarking_sequence( clifford, seed=seed, interleaved_gate=interleaved_gate) pulse_list = rb.decompose_clifford_seq( cl_seq, gate_decomp=self.gate_decomposition) if self.purity: idx = sp1d_idx if self.sweep_type['seeds'] == 0 else sp2d_idx pulse_list += [self.tomo_pulses[idx % 3]] pulse_op_codes_list += [pulse_list] rb_block_list = [ self.block_from_ops(f"rb_{task['qb']}", [ f"{p} {task['qb']}" for p in pulse_op_codes_list[0 if self.identical_pulses else i] ]) for i, task in enumerate(self.preprocessed_task_list) ] return self.simultaneous_blocks(f'sim_rb_{sp1d_idx}{sp1d_idx}', rb_block_list, block_align='end', destroy=self.fast_mode)
def test_recovery_Y180_irb(self): cliffords = [0, 1, 50, 100] nr_seeds = 100 for cl in cliffords: for _ in range(nr_seeds): cl_seq = rb.randomized_benchmarking_sequence( cl, desired_net_cl=0, interleaved_gate='Y180') for decomp in ['HZ', 'XY']: pulse_keys = rb.decompose_clifford_seq(cl_seq, gate_decomp=decomp) gproduct = qtp.tensor(qtp.identity(2)) for pk in pulse_keys: gproduct = self.standard_pulses[pk] * gproduct x = gproduct.full() / gproduct.full()[0][0] self.assertTrue( np.all((np.allclose(np.real(x), np.eye(2)), np.allclose(np.imag(x), np.zeros(2)))))
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 randomized_renchmarking_seqs(qb_name, operation_dict, cliffords, nr_seeds=None, net_clifford=0, gate_decomposition='HZ', interleaved_gate=None, upload=True, cl_sequence=None, sampling_seeds=None, cal_points=None, prep_params=dict()): """ Args qb_name (str): name of qubit operation_dict (dict): dict with all pulse dicts of qubit cliffords (array): array of ints specifying the number of random Cliffords to generate in each sequence nr_seeds (array): array of the form np.arange(nr_seeds_value) net_clifford (int): 0 or 1; whether the recovery Clifford returns qubits to ground statea (0) or puts them in the excited states (1) gate_decomposition (str): the decomposition of Clifford gates into primitives; can be "XY", "HZ", or "5Primitives" interleaved_gate (str): pycqed name for a gate upload (bool): whether to upload sequence to AWGs cl_sequence (list): the Clifford sequence to use for all seeds. Can also be lists of lists in which case the user must ensure that len(nr seeds) % len(cl_sequence) == 0. sampling_seeds (array of ints): ints that will be used as seeds for the random generation of Cliffords. Should have the same length as nr_seeds. cal_points (CalibrationPoints): instance of CalibrationPoints prep_params (dict): qubit preparation_params dict """ seq_name = '1Qb_RB_sequence' if sampling_seeds is None: if nr_seeds is None: raise ValueError('Please provide either "sampling_seeds" or ' '"nr_seeds."') sampling_seeds = [None] * len(nr_seeds) else: nr_seeds = np.arange(len(sampling_seeds)) if cl_sequence is not None: if isinstance(cl_sequence[0], list): # if cl_sequence is a list of lists such that # len(nr_seeds) != len(cl_sequence) but # len(nr_seeds) % len(cl_sequence) == 0, # then create as many copies of the lists in cl_sequence until # len(cl_sequence) == len(nr_seeds). assert len(nr_seeds) % len(cl_sequence) == 0 k = len(nr_seeds) // len(cl_sequence) cl_seq_temp = k * cl_sequence sequences = [] for nCl in cliffords: pulse_list_list_all = [] for s in nr_seeds: if cl_sequence is None: cl_seq = rb.randomized_benchmarking_sequence( nCl, desired_net_cl=net_clifford, interleaved_gate=interleaved_gate, seed=sampling_seeds[s]) elif isinstance(cl_sequence[0], list): cl_seq = cl_seq_temp[s] else: cl_seq = cl_sequence pulse_keys = rb.decompose_clifford_seq( cl_seq, gate_decomp=gate_decomposition) # to avoid having only virtual gates in segment: pulse_keys = ['I'] + pulse_keys pulse_list = [ operation_dict[x + ' ' + qb_name] for x in pulse_keys ] pulse_list += [operation_dict['RO ' + qb_name]] pulse_list_w_prep = add_preparation_pulses(pulse_list, operation_dict, [qb_name], **prep_params) pulse_list_list_all.append(pulse_list_w_prep) seq = pulse_list_list_seq(pulse_list_list_all, seq_name + f'_{nCl}', upload=False) if cal_points is not None: seq.extend( cal_points.create_segments(operation_dict, **prep_params)) sequences.append(seq) # reuse sequencer memory by repeating readout pattern [s.repeat_ro(f"RO {qb_name}", operation_dict) for s in sequences] if upload: ps.Pulsar.get_instance().program_awgs(sequences[0]) return sequences, np.arange(sequences[0].n_acq_elements()), \ np.arange(len(cliffords))
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