Exemplo n.º 1
0
def FastFeedbackControl(latency, qubit_idx: int, platf_cfg: str):
    """
    Single qubit sequence to test fast feedback control (fast conditional
    execution).
    Writes output files to the directory specified in openql.
    Output directory is set as an attribute to the program for convenience.

    Input pars:
        latency:        the waiting time between measurement and the feedback
                          pulse, which should be longer than the feedback
                          latency.
        feedback:       if apply
        qubit_idx:      int specifying the target qubit (starting at 0)
        platf_cfg:      filename of the platform config file
    Returns:
        p:              OpenQL Program object containing


    """
    p = oqh.create_program("FastFeedbackControl", platf_cfg)

    k = oqh.create_kernel("FastFdbkCtrl_nofb", p)
    k.prepz(qubit_idx)
    k.gate('rx90', [qubit_idx])
    # k.gate('rx180', [qubit_idx])
    k.measure(qubit_idx)
    wait_nanoseconds = int(round(latency/1e-9))
    k.gate("wait", [qubit_idx], wait_nanoseconds)
    k.gate("i", [qubit_idx])
    k.measure(qubit_idx)

    p.add_kernel(k)

    k = oqh.create_kernel("FastFdbkCtrl_fb0", p)
    k.prepz(qubit_idx)
    k.gate('rx90', [qubit_idx])
    # k.gate('rx180', [qubit_idx])
    k.measure(qubit_idx)
    wait_nanoseconds = int(round(latency/1e-9))
    k.gate("wait", [qubit_idx], wait_nanoseconds)
    k.gate('C0rx180', [qubit_idx])  # fast feedback control here
    k.measure(qubit_idx)
    p.add_kernel(k)

    k = oqh.create_kernel("FastFdbkCtrl_fb1", p)
    k.prepz(qubit_idx)
    k.gate('rx90', [qubit_idx])
    # k.gate('rx180', [qubit_idx])
    k.measure(qubit_idx)
    wait_nanoseconds = int(round(latency/1e-9))
    k.gate("wait", [qubit_idx], wait_nanoseconds)
    k.gate('C1rx180', [qubit_idx])  # fast feedback control here
    k.measure(qubit_idx)
    p.add_kernel(k)

    # adding the calibration points
    oqh.add_single_qubit_cal_points(p,  qubit_idx=qubit_idx)

    p = oqh.compile(p)
    return p
Exemplo n.º 2
0
def echo(times, qubit_idx: int, platf_cfg: str):
    """
    Single qubit Echo sequence.
    Writes output files to the directory specified in openql.
    Output directory is set as an attribute to the program for convenience.

    Input pars:
        times:          the list of waiting times for each Echo element
        qubit_idx:      int specifying the target qubit (starting at 0)
        platf_cfg:      filename of the platform config file
    Returns:
        p:              OpenQL Program object containing

    """
    p = oqh.create_program("echo", platf_cfg)

    for i, time in enumerate(times[:-4]):
        k = oqh.create_kernel("echo_{}".format(i), p)
        k.prepz(qubit_idx)
        # nr_clocks = int(time/20e-9/2)
        wait_nanoseconds = int(round(time/1e-9/2))
        k.gate('rx90', [qubit_idx])
        k.gate("wait", [qubit_idx], wait_nanoseconds)
        k.gate('rx180', [qubit_idx])
        k.gate("wait", [qubit_idx], wait_nanoseconds)
        k.gate('rx90', [qubit_idx])
        k.measure(qubit_idx)
        p.add_kernel(k)

    # adding the calibration points
    oqh.add_single_qubit_cal_points(p,  qubit_idx=qubit_idx)

    p = oqh.compile(p)
    return p
Exemplo n.º 3
0
def FluxTimingCalibration(qubit_idx: int, times, platf_cfg: str,
                          cal_points: bool=True):
    """
    A Ramsey sequence with varying waiting times `times` around a flux pulse.
    """
    p = oqh.create_program('FluxTimingCalibration', platf_cfg)

    # don't use last 4 points if calibration points are used
    if cal_points:
        times = times[:-4]
    for t in times:
        t_nanoseconds = int(round(t/1e-9))
        k = oqh.create_kernel('pi-flux-pi', p)
        k.prepz(qubit_idx)
        k.gate('rx90', [qubit_idx])
        k.gate('fl_cw_02', [2, 0])
        if t_nanoseconds > 10:
            k.gate("wait", [qubit_idx], t_nanoseconds)
        k.gate('rx90', [qubit_idx])
        k.measure(qubit_idx)
        p.add_kernel(k)

    if cal_points:
        oqh.add_single_qubit_cal_points(p,  qubit_idx=qubit_idx)
    p = oqh.compile(p)
    return p
Exemplo n.º 4
0
def FluxTimingCalibration(qubit_idx: int, times, platf_cfg: str,
                          flux_cw: str='fl_cw_02',
                          qubit_other_idx=0,
                          cal_points: bool=True):
    """
    A Ramsey sequence with varying waiting times `times` around a flux pulse.
    """
    p = oqh.create_program('FluxTimingCalibration', platf_cfg)

    # don't use last 4 points if calibration points are used
    if cal_points:
        times = times[:-4]
    for i_t,t in enumerate(times):
        t_nanoseconds = int(round(t/1e-9))
        k = oqh.create_kernel('pi_flux_pi_{}'.format(i_t), p)
        k.prepz(qubit_idx)
        k.gate('rx90', [qubit_idx])
        # k.gate("wait", [0, 1, 2, 3, 4, 5, 6], 0) #alignment workaround
        k.gate("wait", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 0) #alignment workaround
        # k.gate(flux_cw, [2, 0])
        k.gate('sf_square', [qubit_idx])
        if t_nanoseconds > 10:
            # k.gate("wait", [0, 1, 2, 3, 4, 5, 6], t_nanoseconds)
            k.gate("wait", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], t_nanoseconds) #alignment workaround
            # k.gate("wait", [qubit_idx], t_nanoseconds)
        k.gate('rx90', [qubit_idx])
        k.measure(qubit_idx)
        p.add_kernel(k)

    if cal_points:
        oqh.add_single_qubit_cal_points(p,  qubit_idx=qubit_idx)
    p = oqh.compile(p)
    return p
def complex_Ramsey(times, qubit_idx: int, platf_cfg: str):
    """
    Single qubit Ramsey sequence.
    Writes output files to the directory specified in openql.
    Output directory is set as an attribute to the program for convenience.

    Input pars:
        times:          the list of waiting times for each Ramsey element
        qubit_idx:      int specifying the target qubit (starting at 0)
        platf_cfg:      filename of the platform config file
    Returns:
        p:              OpenQL Program object containing

    """
    p = oqh.create_program("complex_Ramsey", platf_cfg)

    prerotations = ['rx90', 'rym90']
    timeloop = times[:-4][::2]
    for i, time in enumerate(timeloop):
        for rot in prerotations:
            k = oqh.create_kernel("Ramsey_" + rot + "_{}".format(i), p)
            k.prepz(qubit_idx)
            wait_nanoseconds = int(round(time / 1e-9))
            k.gate('rx90', [qubit_idx])
            k.gate("wait", [qubit_idx], wait_nanoseconds)
            k.gate(rot, [qubit_idx])
            k.measure(qubit_idx)
            p.add_kernel(k)

    # adding the calibration points
    oqh.add_single_qubit_cal_points(p, qubit_idx=qubit_idx)

    p = oqh.compile(p)
    return p
def T1(qubit_idx: int,
       platf_cfg: str,
       times: list,
       nr_cz_instead_of_idle_time: list = None,
       qb_cz_idx: int = None,
       nr_flux_dance: float = None,
       wait_time_after_flux_dance: float = 0):
    """
    Single qubit T1 sequence.
    Writes output files to the directory specified in openql.
    Output directory is set as an attribute to the program for convenience.

    Input pars:
        times:          the list of waiting times for each T1 element
        qubit_idx:      int specifying the target qubit (starting at 0)
        platf_cfg:      filename of the platform config file
    Returns:
        p:              OpenQL Program object containing


    """
    p = oqh.create_program('T1', platf_cfg)

    for i, time in enumerate(times[:-4]):
        k = oqh.create_kernel('T1_{}'.format(i), p)
        k.prepz(qubit_idx)

        if nr_flux_dance:
            for _ in range(int(nr_flux_dance)):
                for step in [1, 2, 3, 4]:
                    # if refocusing:
                    #     k.gate(f'flux-dance-{step}-refocus', [0])
                    # else:
                    k.gate(f'flux-dance-{step}', [0])
                k.gate("wait", [], 0)  # alignment
            k.gate("wait", [], wait_time_after_flux_dance)

        k.gate('rx180', [qubit_idx])

        if nr_cz_instead_of_idle_time is not None:
            for n in range(nr_cz_instead_of_idle_time[i]):
                k.gate("cz", [qubit_idx, qb_cz_idx])
            k.gate("wait", [], 0)  # alignment
            k.gate("wait", [], wait_time_after_flux_dance)
        else:
            wait_nanoseconds = int(round(time / 1e-9))
            k.gate("wait", [qubit_idx], wait_nanoseconds)

        k.measure(qubit_idx)
        p.add_kernel(k)

    # adding the calibration points
    oqh.add_single_qubit_cal_points(p, qubit_idx=qubit_idx)

    p = oqh.compile(p)
    return p
def spin_lock_echo(times, qubit_idx: int, platf_cfg: str):
    """
    Single qubit Echo sequence.
    Writes output files to the directory specified in openql.
    Output directory is set as an attribute to the program for convenience.

    Input pars:
        times:          the list of waiting times for each Echo element
        qubit_idx:      int specifying the target qubit (starting at 0)
        platf_cfg:      filename of the platform config file
    Returns:
        p:              OpenQL Program object containing

    """
    p = oqh.create_program("spin_lock_echo", platf_cfg)

    for i, time in enumerate(times[:-4]):

        k = oqh.create_kernel("spin_lock_echo{}".format(i), p)
        k.prepz(qubit_idx)
        # nr_clocks = int(time/20e-9/2)
        square_us_cycles = np.floor(time / 1e-6).astype(int)
        square_ns_cycles = np.round(
            (time % 1e-6) / mw_gate_duration).astype(int)
        wait_nanoseconds = 1
        # print("square_us_cycles", square_us_cycles)
        # print("square_us_cycles", square_ns_cycles)
        k.gate('rYm90', [qubit_idx])
        k.gate("wait", [qubit_idx], wait_nanoseconds)
        k.gate('rx180', [qubit_idx])
        k.gate("wait", [qubit_idx], wait_nanoseconds)
        for suc in range(square_us_cycles):
            k.gate('cw_10',
                   [qubit_idx])  # make sure that the square pulse lasts 1us
        for snc in range(square_ns_cycles):
            k.gate('cw_11', [
                qubit_idx
            ])  # make sure that the square pulse lasts mw_gate_duration ns
        k.gate("wait", [qubit_idx], wait_nanoseconds)
        k.gate('rx180', [qubit_idx])
        k.gate("wait", [qubit_idx], wait_nanoseconds)
        k.gate('rYm90', [qubit_idx])
        k.measure(qubit_idx)
        p.add_kernel(k)

    # adding the calibration points
    oqh.add_single_qubit_cal_points(p, qubit_idx=qubit_idx)

    p = oqh.compile(p)
    return p
def CPMG_SO(orders, tauN: int, qubit_idx: int, platf_cfg: str):
    """
    Single qubit CPMG sequence.
    Writes output files to the directory specified in openql.
    Output directory is set as an attribute to the program for convenience.

    Input pars:
        times:          the list of waiting times for each Echo element
        qubit_idx:      int specifying the target qubit (starting at 0)
        platf_cfg:      filename of the platform config file
    Returns:
        p:              OpenQL Program object containing

    """
    p = oqh.create_program("CPMG_SO", platf_cfg)

    for i, order in enumerate(orders[:-4]):

        k = oqh.create_kernel("CPMG_SO_{}".format(i), p)
        k.prepz(qubit_idx)
        # nr_clocks = int(time/20e-9/2)

        wait_nanoseconds = int(round((tauN / 1e-9) / 2))
        k.gate('rx90', [qubit_idx])
        k.gate("wait", [qubit_idx], wait_nanoseconds)
        for j in range(order - 1):
            k.gate('ry180', [qubit_idx])
            k.gate("wait", [qubit_idx], 2 * wait_nanoseconds)
        k.gate('ry180', [qubit_idx])
        k.gate("wait", [qubit_idx], wait_nanoseconds)
        # angle = (i*40)%360
        # cw_idx = angle//20 + 9
        # if angle == 0:
        k.gate('rx90', [qubit_idx])
        # else:
        #     k.gate('cw_{:02}'.format(cw_idx), [qubit_idx])

        k.measure(qubit_idx)
        p.add_kernel(k)

    # adding the calibration points
    oqh.add_single_qubit_cal_points(p, qubit_idx=qubit_idx)

    p = oqh.compile(p)
    return p
Exemplo n.º 9
0
def T1_second_excited_state(times, qubit_idx: int, platf_cfg: str):
    """
    Single qubit T1 sequence for the second excited states.
    Writes output files to the directory specified in openql.
    Output directory is set as an attribute to the program for convenience.

    Input pars:
        times:          the list of waiting times for each T1 element
        qubit_idx:      int specifying the target qubit (starting at 0)
        platf_cfg:      filename of the platform config file
    Returns:
        p:              OpenQL Program object containing


    """
    p = oqh.create_program("T1_2nd_exc", platf_cfg)

    for i, time in enumerate(times):
        for j in range(2):
            k = oqh.create_kernel("T1_2nd_exc_{}_{}".format(i, j), p)
            k.prepz(qubit_idx)
            wait_nanoseconds = int(round(time / 1e-9))
            k.gate('rx180', [qubit_idx])
            k.gate('rx12', [qubit_idx])
            k.gate("wait", [qubit_idx], wait_nanoseconds)
            if j == 1:
                k.gate('rx180', [qubit_idx])
            k.measure(qubit_idx)
            p.add_kernel(k)

    # adding the calibration points
    oqh.add_single_qubit_cal_points(p,
                                    qubit_idx=qubit_idx,
                                    f_state_cal_pts=True)

    dt = times[1] - times[0]
    sweep_points = np.concatenate(
        [np.repeat(times, 2), times[-1] + dt * np.arange(6) + dt])
    # attribute get's added to program to help finding the output files
    p.sweep_points = sweep_points

    p = oqh.compile(p)
    return p
Exemplo n.º 10
0
def ef_rabi_seq(q0: int,
                amps: list,
                platf_cfg: str,
                recovery_pulse: bool = True,
                add_cal_points: bool = True):
    """
    Sequence used to calibrate pulses for 2nd excited state (ef/12 transition)

    Timing of the sequence:
    q0:   --   X180 -- X12 -- (X180) -- RO

    Args:
        q0      (str): name of the addressed qubit
        amps   (list): amps for the two state pulse, note that these are only
            used to label the kernels. Load the pulse in the LutMan
        recovery_pulse (bool): if True adds a recovery pulse to enhance
            contrast in the measured signal.
    """
    if len(amps) > 18:
        raise ValueError('Only 18 free codewords available for amp pulses')

    p = oqh.create_program("ef_rabi_seq", platf_cfg)
    # These angles correspond to special pi/2 pulses in the lutman
    for i, amp in enumerate(amps):
        # cw_idx corresponds to special hardcoded pulses in the lutman
        cw_idx = i + 9

        k = oqh.create_kernel("ef_A{}".format(int(abs(1000 * amp))), p)
        k.prepz(q0)
        k.gate('rx180', [q0])
        k.gate('cw_{:02}'.format(cw_idx), [q0])
        if recovery_pulse:
            k.gate('rx180', [q0])
        k.measure(q0)
        p.add_kernel(k)
    if add_cal_points:
        p = oqh.add_single_qubit_cal_points(p, qubit_idx=q0)

    p = oqh.compile(p)

    if add_cal_points:
        cal_pts_idx = [
            amps[-1] + .1, amps[-1] + .15, amps[-1] + .2, amps[-1] + .25
        ]
    else:
        cal_pts_idx = []

    p.sweep_points = np.concatenate([amps, cal_pts_idx])
    # FIXME: remove try-except, when we depend hardly on >=openql-0.6
    try:
        p.set_sweep_points(p.sweep_points)
    except TypeError:
        # openql-0.5 compatibility
        p.set_sweep_points(p.sweep_points, len(p.sweep_points))
    return p
Exemplo n.º 11
0
                                    k.gate(
                                        flux_codeword,
                                        [qubit_map[qubit] for qubit in qubit_or_qubits],
                                    )
                                    k.gate("wait", [], 0)

                        k.gate("wait", [], 0)  # align RO
                        for qubit_idx in qubit_map.values():
                            k.measure(qubit_idx)  # measure parking qubit only
                        k.gate("wait", [], 0)
                        p.add_kernel(k)

        if cal_points:
            if number_of_qubits == 1:
                p = oqh.add_single_qubit_cal_points(
                    p, qubit_idx=qubits[0], f_state_cal_pts=f_state_cal_pts
                )
            elif number_of_qubits == 2:
                if f_state_cal_pts:
                    combinations = ["00", "01", "10", "11", "02", "20", "22"]
                else:
                    combinations = ["00", "01", "10", "11"]
                p = oqh.add_multi_q_cal_points(
                    p, qubits=qubits, combinations=combinations
                )
            elif number_of_qubits == 3:
                p = oqh.add_single_qubit_cal_points(
                    p,
                    qubit_idx=qubit_map["q2"],
                    f_state_cal_pts=f_state_cal_pts,
                    # we must measure all 3 qubits to avoid alignment issues
Exemplo n.º 12
0
def randomized_benchmarking(qubits: list,
                            platf_cfg: str,
                            nr_cliffords,
                            nr_seeds: int,
                            net_cliffords: list = [0],
                            max_clifford_idx: int = 11520,
                            flux_codeword: str = 'cz',
                            simultaneous_single_qubit_RB=False,
                            initialize: bool = True,
                            interleaving_cliffords=[None],
                            program_name: str = 'randomized_benchmarking',
                            cal_points: bool = True,
                            f_state_cal_pts: bool = True,
                            sim_cz_qubits: list = None,
                            recompile: bool = True):
    '''
    Input pars:
        qubits:         list of ints specifying qubit indices.
                        based on the length this function detects if it should
                        generate a single or two qubit RB sequence.
        platf_cfg:      filename of the platform config file
        nr_cliffords:   list nr_cliffords for which to generate RB seqs
        nr_seeds:       int  nr_seeds for which to generate RB seqs
        net_cliffords:  list of ints index of net clifford the sequence
                        should perform. See examples below on how to use this.
                            Important clifford indices
                                0 -> Idx
                                3 -> rx180
                                3*24+3 -> {rx180 q0 | rx180 q1}
                                4368 -> CZ

        max_clifford_idx:   Set's the maximum clifford group index from which
                        to sample random cliffords.
                            Important clifford indices
                                24 -> Size of the single qubit Cl group
                                576  -> Size of the single qubit like class
                                    contained in the two qubit Cl group
                                11520 -> Size of the complete two qubit Cl group

        initialize:     if True initializes qubits to 0, disable for restless
                        tuning
        interleaving_cliffords: list of integers which specifies which cliffords
                        to interleave the sequence with (for interleaved RB)
        program_name:           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)
        sim_cz_qubits:
                        A list of qubit indices on which a simultaneous cz 
                        instruction must be applied. This is for characterizing
                        CZ gates that are intended to be performed in parallel 
                        with other CZ gates. 
        recompile:      True -> compiles the program,
                        'as needed' -> compares program to timestamp of config
                            and existence, if required recompile.
                        False -> compares program to timestamp of config.
                            if compilation is required raises a ValueError

                        If the program is more recent than the config
                        it returns an empty OpenQL program object with
                        the intended filename that can be used to upload the
                        previously compiled file.

    Returns:
        p:              OpenQL Program object

    ***************************************************************************
    Examples:
        1. Single qubit randomized benchmarking:

            p = cl_oql.randomized_benchmarking(
                qubits=[0],

                nr_cliffords=[2, 4, 8, 16, 32, 128, 512, 1024],
                nr_seeds=1,  # for CCL memory reasons
                platf_cfg=qubit.cfg_openql_platform_fn(),
                program_name='RB_{}'.format(i))

        2. Two qubit simultaneous randomized benchmarking:

            p = cl_oql.randomized_benchmarking(
                qubits=[0, 1],          # simultaneous RB on both qubits
                simultaneous_single_qubit_RB=True,
                nr_cliffords=[2, 4, 8, 16, 32, 128, 512, 1024],
                nr_seeds=1,  # for CCL memory reasons
                platf_cfg=qubit.cfg_openql_platform_fn(),
                program_name='RB_{}'.format(i))

        3. Single qubit interleaved randomized benchmarking:
            p = cl_oql.randomized_benchmarking(
                qubits=[0],
                interleaving_cliffords=[None, 0, 16, 3],
                cal_points=False # relevant here because of data binning

                nr_cliffords=[2, 4, 8, 16, 32, 128, 512, 1024],
                nr_seeds=1,
                platf_cfg=qubit.cfg_openql_platform_fn(),
                program_name='Interleaved_RB_s{}_int{}_ncl{}_{}'.format(i))

    '''
    p = oqh.create_program(program_name, platf_cfg)

    # attribute get's added to program to help finding the output files
    p.filename = join(p.output_dir,
                      p.name + '.qisa')  # FIXME: platform dependency

    if not oqh.check_recompilation_needed(
            program_fn=p.filename, platf_cfg=platf_cfg, recompile=recompile):
        return p

    if len(qubits) == 1:
        qubit_map = {'q0': qubits[0]}
        number_of_qubits = 1
        Cl = SingleQubitClifford
    elif len(qubits) == 2 and not simultaneous_single_qubit_RB:
        qubit_map = {'q0': qubits[0], 'q1': qubits[1]}
        number_of_qubits = 2
        Cl = TwoQubitClifford
    elif len(qubits) == 2 and simultaneous_single_qubit_RB:
        qubit_map = {'q0': qubits[0], 'q1': qubits[1]}
        # arguments used to generate 2 single qubit sequences
        number_of_qubits = 2
        Cl = SingleQubitClifford
    else:
        raise NotImplementedError()

    for seed in range(nr_seeds):
        for j, n_cl in enumerate(nr_cliffords):
            for interleaving_cl in interleaving_cliffords:
                if not simultaneous_single_qubit_RB:
                    cl_seq = rb.randomized_benchmarking_sequence(
                        n_cl,
                        number_of_qubits=number_of_qubits,
                        desired_net_cl=None,  # net_clifford,
                        max_clifford_idx=max_clifford_idx,
                        interleaving_cl=interleaving_cl)
                    net_cl_seq = rb.calculate_net_clifford(cl_seq, Cl)
                    cl_seq_decomposed = []
                    for cl in cl_seq:
                        # FIXME: hacking in exception for benchmarking only CZ
                        # (not as a member of CNOT group)
                        if cl == -4368:
                            cl_seq_decomposed.append([('CZ', ['q0', 'q1'])])
                        else:
                            cl_seq_decomposed.append(Cl(cl).gate_decomposition)
                    for net_clifford in net_cliffords:
                        recovery_to_idx_clifford = net_cl_seq.get_inverse()
                        recovery_clifford = Cl(
                            net_clifford) * recovery_to_idx_clifford
                        cl_seq_decomposed_with_net = cl_seq_decomposed + \
                            [recovery_clifford.gate_decomposition]
                        k = oqh.create_kernel(
                            'RB_{}Cl_s{}_net{}_inter{}'.format(
                                int(n_cl), seed, net_clifford,
                                interleaving_cl), p)
                        if initialize:
                            for qubit_idx in qubit_map.values():
                                k.prepz(qubit_idx)

                        for gates in cl_seq_decomposed_with_net:
                            for g, q in gates:
                                if isinstance(q, str):
                                    k.gate(g, [qubit_map[q]])
                                elif isinstance(q, list):
                                    if sim_cz_qubits is None:
                                        k.gate("wait",
                                               list(qubit_map.values()), 0)
                                        k.gate(
                                            flux_codeword,
                                            list(qubit_map.values()),
                                        )  # fix for QCC
                                        k.gate("wait",
                                               list(qubit_map.values()), 0)
                                    else:
                                        # A simultaneous CZ is applied to characterize cz gates that
                                        # have been calibrated to be used in parallel.
                                        k.gate(
                                            "wait",
                                            list(qubit_map.values()) +
                                            sim_cz_qubits, 0)
                                        k.gate(
                                            flux_codeword,
                                            list(qubit_map.values()),
                                        )  # fix for QCC
                                        k.gate(flux_codeword,
                                               sim_cz_qubits)  # fix for QCC
                                        k.gate(
                                            "wait",
                                            list(qubit_map.values()) +
                                            sim_cz_qubits, 0)

                        # FIXME: This hack is required to align multiplexed RO in openQL..
                        k.gate("wait", list(qubit_map.values()), 0)
                        for qubit_idx in qubit_map.values():
                            k.measure(qubit_idx)
                        k.gate("wait", list(qubit_map.values()), 0)
                        p.add_kernel(k)
                elif simultaneous_single_qubit_RB:
                    for net_clifford in net_cliffords:
                        k = oqh.create_kernel(
                            'RB_{}Cl_s{}_net{}_inter{}'.format(
                                int(n_cl), seed, net_clifford,
                                interleaving_cl), p)
                        if initialize:
                            for qubit_idx in qubit_map.values():
                                k.prepz(qubit_idx)

                        # FIXME: Gate seqs is a hack for failing openql scheduling
                        gate_seqs = [[], []]
                        for gsi, q_idx in enumerate(qubits):
                            cl_seq = rb.randomized_benchmarking_sequence(
                                n_cl,
                                number_of_qubits=1,
                                desired_net_cl=net_clifford,
                                interleaving_cl=interleaving_cl)
                            for cl in cl_seq:
                                gates = Cl(cl).gate_decomposition
                                # for g, q in gates:
                                #     k.gate(g, q_idx)

                                # FIXME: THIS is a hack because of OpenQL
                                # scheduling issues #157

                                gate_seqs[gsi] += gates
                        # OpenQL #157 HACK
                        l = max([len(gate_seqs[0]), len(gate_seqs[1])])

                        for gi in range(l):
                            for gj, q_idx in enumerate(qubits):
                                # gj = 0
                                # q_idx = 0
                                try:  # for possible different lengths in gate_seqs
                                    g = gate_seqs[gj][gi]
                                    k.gate(g[0], [q_idx])
                                except IndexError as e:
                                    pass
                        # end of #157 HACK
                        # FIXME: This hack is required to align multiplexed RO in openQL..
                        k.gate("wait", list(qubit_map.values()), 0)
                        for qubit_idx in qubit_map.values():
                            k.measure(qubit_idx)
                        k.gate("wait", list(qubit_map.values()), 0)
                        p.add_kernel(k)

        if cal_points:
            if number_of_qubits == 1:
                p = oqh.add_single_qubit_cal_points(
                    p, qubit_idx=qubits[0], f_state_cal_pts=f_state_cal_pts)
            elif number_of_qubits == 2:

                if f_state_cal_pts:
                    combinations = ['00', '01', '10', '11', '02', '20', '22']
                else:
                    combinations = ['00', '01', '10', '11']
                p = oqh.add_multi_q_cal_points(p,
                                               qubits=qubits,
                                               combinations=combinations)

    p = oqh.compile(p)
    return p
Exemplo n.º 13
0
def rabi_frequency(times,
                   qubit_idx: int,
                   platf_cfg: str,
                   mw_gate_duration: float = 40e-9,
                   tomo: bool = False):
    """
    Rabi Sequence consising out of sequence of square pulses
    Writes output files to the directory specified in openql.
    Output directory is set as an attribute to the program for convenience.

    Input pars:
        times:          the list of waiting times for each Echo element
        qubit_idx:      int specifying the target qubit (starting at 0)
        platf_cfg:      filename of the platform config file
    Returns:
        p:              OpenQL Program object containing

    """
    p = oqh.create_program("rabi_frequency", platf_cfg)

    if tomo:
        tomo_gates = ['I', 'rX180', 'rX12']
    else:
        tomo_gates = ['I']

    if tomo:
        timeloop = times[:-6][::3]
    else:
        timeloop = times[:-4]

    for i, time in enumerate(timeloop):
        for tomo_gate in tomo_gates:
            k = oqh.create_kernel(
                "rabi_frequency" + "_tomo_" + tomo_gate + "{}".format(i), p)
            k.prepz(qubit_idx)
            # nr_clocks = int(time/20e-9/2)
            square_us_cycles = np.floor((time + 1e-10) / 1e-6).astype(int)
            leftover_us = (time - square_us_cycles * 1e-6)
            square_ns_cycles = np.floor(
                (leftover_us + 1e-10) / mw_gate_duration).astype(int)
            leftover_ns = (leftover_us - square_ns_cycles * mw_gate_duration)
            print(leftover_us)
            print(leftover_ns)
            mwlutman_index = np.round((leftover_ns + 1e-10) / 4e-9).astype(int)
            print(mwlutman_index)
            print("square_us_cycles", square_us_cycles)
            print("square_ns_cycles", square_ns_cycles)
            for suc in range(square_us_cycles):
                k.gate(
                    'cw_10',
                    [qubit_idx])  # make sure that the square pulse lasts 1us
            for snc in range(square_ns_cycles):
                k.gate('cw_11', [
                    qubit_idx
                ])  # make sure that the square pulse lasts mw_gate_duration ns
            k.gate('cw_{}'.format(mwlutman_index + 11), [qubit_idx])
            if tomo:
                k.gate(tomo_gate, [qubit_idx])
            k.measure(qubit_idx)
            p.add_kernel(k)

    # adding the calibration points
    oqh.add_single_qubit_cal_points(p,
                                    qubit_idx=qubit_idx,
                                    f_state_cal_pts=tomo)

    p = oqh.compile(p)
    return p
Exemplo n.º 14
0
def spin_lock_simple(times,
                     qubit_idx: int,
                     platf_cfg: str,
                     mw_gate_duration: float = 40e-9,
                     tomo: bool = False):
    """
    Single qubit Echo sequence.
    Writes output files to the directory specified in openql.
    Output directory is set as an attribute to the program for convenience.

    Input pars:
        times:          the list of waiting times for each Echo element
        qubit_idx:      int specifying the target qubit (starting at 0)
        platf_cfg:      filename of the platform config file
    Returns:
        p:              OpenQL Program object containing

    """
    p = oqh.create_program("spin_lock_simple", platf_cfg)
    # Poor mans tomography:
    if tomo:
        tomo_gates = ['I', 'rX180', 'rX12']
    else:
        tomo_gates = ['I']

    if tomo:
        timeloop = times[:-6][::3]
    else:
        timeloop = times[:-4]

    for i, time in enumerate(timeloop):
        for tomo_gate in tomo_gates:
            k = oqh.create_kernel(
                "spin_lock_simple" + "_tomo_" + tomo_gate + "_{}".format(i), p)
            k.prepz(qubit_idx)
            # nr_clocks = int(time/20e-9/2)
            square_us_cycles = np.floor(time / 1e-6).astype(int)
            square_ns_cycles = np.round(
                (time % 1e-6) / mw_gate_duration).astype(int)
            # print("square_us_cycles", square_us_cycles)
            # print("square_us_cycles", square_ns_cycles)
            k.gate('rYm90', [qubit_idx])
            for suc in range(square_us_cycles):
                k.gate(
                    'cw_10',
                    [qubit_idx])  # make sure that the square pulse lasts 1us
            for snc in range(square_ns_cycles):
                k.gate('cw_11', [
                    qubit_idx
                ])  # make sure that the square pulse lasts mw_gate_duration ns
            k.gate('rYm90', [qubit_idx])
            if tomo:
                k.gate(tomo_gate, [qubit_idx])
            k.measure(qubit_idx)
            p.add_kernel(k)

    # adding the calibration points
    oqh.add_single_qubit_cal_points(p,
                                    qubit_idx=qubit_idx,
                                    f_state_cal_pts=tomo)
    p = oqh.compile(p)
    return p