Пример #1
0
 def test_drag(self):
     """Test discrete sampled drag pulse."""
     amp = 0.5
     sigma = 0.1
     beta = 0
     duration = 10
     center = 10/2
     times = np.arange(0, duration) + 0.5
     # reference drag pulse
     drag_ref = continuous.drag(times, amp, center, sigma, beta=beta,
                                zeroed_width=2*(center+1), rescale_amp=True)
     drag_pulse = library.drag(duration, amp, sigma, beta=beta)
     self.assertIsInstance(drag_pulse, Waveform)
     np.testing.assert_array_almost_equal(drag_pulse.samples, drag_ref)
Пример #2
0
def _fit_drag_func(duration, amp, sigma, beta, exp_samples):
    """
    Helper function to compare a drag pulse to samples from
    the experiment

    Args:
        duration (int): pulse duration
        amp (complex): gauss amp
        sigma (float): gauss sigma
        beta (complex): drag amp
        exp_samples (ndarray): the experiment pulse, split into real and imag

    Returns:
        ndarray: difference between the drag and experimental samples

    """

    fit_pulse = pulse_lib.drag(
        duration=duration, amp=amp, sigma=sigma, beta=beta).samples * np.exp(
            -1j * np.pi / 2)

    return np.concatenate((fit_pulse.real, fit_pulse.imag)) - exp_samples
Пример #3
0
def drag_schedules(beta_list,
                   qubits,
                   pulse_amp,
                   pulse_width,
                   pulse_sigma=None,
                   width_sigma_ratio=4,
                   drives=None,
                   inst_map=None,
                   meas_map=None):
    """
    Generates schedules for a drag experiment doing a pulse then
    the - pulse

    Args:
        beta_list (list of floats): List of relative amplitudes
        for the derivative pulse
        qubits (list of integers): indices of the qubits to perform a rabi
        pulse_amp (list): amp of the gaussian (list of length qubits)
        pulse_width (float): width of gaussian (in dt units)
        pulse_sigma (float): sigma of gaussian
        width_sigma_ratio (int): set sigma to a certain ratio of the width (use
            if pulse_sigma is None)
        drives (list): list of :class:`~qiskit.pulse.DriveChannel` objects
        inst_map (InstructionScheduleMap): InstructionScheduleMap object to use
        meas_map (list): meas_map to use

    Returns:
       A list of QuantumSchedules
       xdata: a list of amps

    Raises:
        QiskitError: when necessary variables are not supplied.
    """
    xdata = beta_list

    # copy the instruction to schedule mapping
    inst_map = copy.deepcopy(inst_map)

    # Following variables should not be optional.
    # To keep function interface constant, errors are inserted here.
    # TODO: redesign this function in next release
    if inst_map is None:
        QiskitError(
            'Instruction schedule map is not provided. ',
            'Run `backend.defaults().instruction_schedule_map` to get inst_map.'
        )
    if meas_map is None:
        QiskitError('Measurement map is not provided. ',
                    'Run `backend.configuration().meas_map` to get meas_map.')

    if pulse_sigma is None:
        pulse_sigma = pulse_width / width_sigma_ratio

    # Construct the schedules
    drag_scheds = []
    for index, b_amp in enumerate(beta_list):
        sched = pulse.Schedule(name='dragsched_%d_0' % index)
        for qind, qubit in enumerate(qubits):
            drag_pulse_p = pulse_lib.drag(duration=pulse_width,
                                          amp=pulse_amp[qind],
                                          beta=b_amp,
                                          sigma=pulse_sigma,
                                          name='drag_pulse_%d_%d' %
                                          (index, qubit))
            drag_pulse_m = pulse_lib.drag(duration=pulse_width,
                                          amp=-pulse_amp[qind],
                                          beta=b_amp,
                                          sigma=pulse_sigma,
                                          name='drag_pulse_%d_%d' %
                                          (index, qubit))
            sched += pulse.Play(drag_pulse_p, drives[qubit])
            sched += pulse.Play(drag_pulse_m, drives[qubit])
        sched += measure(qubits, inst_map=inst_map,
                         meas_map=meas_map).shift(pulse_width)
        drag_scheds.append(sched)

    return drag_scheds, xdata
Пример #4
0
def update_u_gates(drag_params,
                   pi2_pulse_schedules=None,
                   qubits=None,
                   inst_map=None,
                   drives=None):
    """Update the cmd_def with new single qubit gate values

    Will update U2, U3

    Args:
        drag_params (list): list of drag params
        pi2_pulse_schedules (list): list of new pi/2 gate as a pulse schedule
                             will use the drag_params if this is None.
        qubits (list): list of qubits to update
        inst_map (InstructionScheduleMap): InstructionScheduleMap providing
            circuit instruction to schedule definitions.
        drives (list): List of drive chs
    """
    # pylint: disable = invalid-name

    # U2 is -P1.Y90p.-P0
    # U3 is -P2.X90p.-P0.X90m.-P1

    for qubit in qubits:

        drive_ch = drives[qubit]

        if pi2_pulse_schedules is None:
            x90_pulse = pulse_lib.drag(**drag_params[qubit])
            x90_sched = Schedule()
            x90_sched += Play(x90_pulse, drive_ch).shift(0)
        else:
            x90_sched = pi2_pulse_schedules[qubit]

        # find channel dependency for u2
        for _u2_group in _find_channel_groups('u2',
                                              qubits=qubit,
                                              inst_map=inst_map):
            if drive_ch in _u2_group:
                break
        else:
            _u2_group = (drive_ch, )

        # find channel dependency for u3
        for _u3_group in _find_channel_groups('u3',
                                              qubits=qubit,
                                              inst_map=inst_map):
            if drive_ch in _u3_group:
                break
        else:
            _u3_group = (drive_ch, )

        # add commands to schedule

        # u2
        with pulse.build(name=f"u2_{qubit}",
                         default_alignment="sequential") as u2_sched:
            P0 = Parameter("P0")
            P1 = Parameter("P1")
            for ch in _u2_group:
                pulse.shift_phase(-P1 + np.pi / 2, ch)
            pulse.call(x90_sched)
            for ch in _u2_group:
                pulse.shift_phase(-P0 - np.pi / 2, ch)

        # u3
        with pulse.build(name=f"u3_{qubit}",
                         default_alignment="sequential") as u3_sched:
            P0 = Parameter("P0")
            P1 = Parameter("P1")
            P2 = Parameter("P2")
            for ch in _u3_group:
                pulse.shift_phase(-P2, ch)
            pulse.call(x90_sched)
            for ch in _u3_group:
                pulse.shift_phase(-P0 - np.pi, ch)
            pulse.call(x90_sched)
            for ch in _u3_group:
                pulse.shift_phase(-P1 + np.pi, ch)

        inst_map.add('u2', qubits=qubit, schedule=u2_sched)
        inst_map.add('u3', qubits=qubit, schedule=u3_sched)
def update_u_gates(drag_params,
                   pi2_pulse_schedules=None,
                   qubits=None,
                   inst_map=None,
                   drives=None):
    """Update the cmd_def with new single qubit gate values

    Will update U2, U3

    Args:
        drag_params (list): list of drag params
        pi2_pulse_schedules (list): list of new pi/2 gate as a pulse schedule
                             will use the drag_params if this is None.
        qubits (list): list of qubits to update
        inst_map (InstructionScheduleMap): InstructionScheduleMap providing
            circuit instruction to schedule definitions.
        drives (list): List of drive chs
    """

    # U2 is -P1.Y90p.-P0
    # U3 is -P2.X90p.-P0.X90m.-P1

    def parametrized_fc(kw_name, phi0, chan, t_offset):
        def _parametrized_fc(**kwargs):
            return ShiftPhase(phase=-kwargs[kw_name] + phi0,
                              channel=chan).shift(t_offset)

        return _parametrized_fc

    for qubit in qubits:

        drive_ch = drives[qubit]

        if pi2_pulse_schedules is None:
            x90_pulse = pulse_lib.drag(**drag_params[qubit])
            x90_sched = Schedule()
            x90_sched += Play(x90_pulse, drive_ch).shift(0)
        else:
            x90_sched = pi2_pulse_schedules[qubit]

        pulse_dur = x90_sched.duration

        # find channel dependency for u2
        for _u2_group in _find_channel_groups('u2',
                                              qubits=qubit,
                                              inst_map=inst_map):
            if drive_ch in _u2_group:
                break
        else:
            _u2_group = (drive_ch, )

        u2_fc1s = [parametrized_fc('P1', np.pi / 2, ch, 0) for ch in _u2_group]
        u2_fc2s = [
            parametrized_fc('P0', -np.pi / 2, ch, pulse_dur)
            for ch in _u2_group
        ]

        # find channel dependency for u3
        for _u3_group in _find_channel_groups('u3',
                                              qubits=qubit,
                                              inst_map=inst_map):
            if drive_ch in _u3_group:
                break
        else:
            _u3_group = (drive_ch, )

        u3_fc1s = [parametrized_fc('P2', 0, ch, 0) for ch in _u3_group]
        u3_fc2s = [
            parametrized_fc('P0', -np.pi, ch, pulse_dur) for ch in _u3_group
        ]
        u3_fc3s = [
            parametrized_fc('P1', np.pi, ch, 2 * pulse_dur) for ch in _u3_group
        ]

        # add commands to schedule
        # u2
        sched_components = [*u2_fc1s, x90_sched, *u2_fc2s]
        schedule1 = ParameterizedSchedule(*sched_components,
                                          parameters=['P0', 'P1'],
                                          name='u2_%d' % qubit)

        # u3
        sched_components = [
            *u3_fc1s, x90_sched, *u3_fc2s,
            x90_sched.shift(pulse_dur), *u3_fc3s
        ]
        schedule2 = ParameterizedSchedule(*sched_components,
                                          parameters=['P0', 'P1', 'P2'],
                                          name='u3_%d' % qubit)

        inst_map.add('u2', qubits=qubit, schedule=schedule1)
        inst_map.add('u3', qubits=qubit, schedule=schedule2)