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)
Example #3
0
    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
Example #5
0
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