Ejemplo n.º 1
0
def schedule(
    circuits: Union[QuantumCircuit, List[QuantumCircuit]],
    backend: Optional[Union[Backend, BaseBackend]] = None,
    inst_map: Optional[InstructionScheduleMap] = None,
    meas_map: Optional[List[List[int]]] = None,
    dt: Optional[float] = None,
    method: Optional[Union[str, List[str]]] = None,
) -> Union[Schedule, List[Schedule]]:
    """
    Schedule a circuit to a pulse ``Schedule``, using the backend, according to any specified
    methods. Supported methods are documented in :py:mod:`qiskit.scheduler.schedule_circuit`.

    Args:
        circuits: The quantum circuit or circuits to translate
        backend: A backend instance, which contains hardware-specific data required for scheduling
        inst_map: Mapping of circuit operations to pulse schedules. If ``None``, defaults to the
                  ``backend``\'s ``instruction_schedule_map``
        meas_map: List of sets of qubits that must be measured together. If ``None``, defaults to
                  the ``backend``\'s ``meas_map``
        dt: The output sample rate of backend control electronics. For scheduled circuits
            which contain time information, dt is required. If not provided, it will be
            obtained from the backend configuration
        method: Optionally specify a particular scheduling method

    Returns:
        A pulse ``Schedule`` that implements the input circuit

    Raises:
        QiskitError: If ``inst_map`` and ``meas_map`` are not passed and ``backend`` is not passed
    """
    start_time = time()
    if inst_map is None:
        if backend is None:
            raise QiskitError(
                "Must supply either a backend or InstructionScheduleMap for scheduling passes."
            )
        defaults = backend.defaults()
        if defaults is None:
            raise QiskitError(
                "The backend defaults are unavailable. The backend may not support pulse."
            )
        inst_map = defaults.instruction_schedule_map
    if meas_map is None:
        if backend is None:
            raise QiskitError("Must supply either a backend or a meas_map for scheduling passes.")
        meas_map = backend.configuration().meas_map
    if dt is None:
        if backend is not None:
            dt = backend.configuration().dt

    schedule_config = ScheduleConfig(inst_map=inst_map, meas_map=meas_map, dt=dt)
    circuits = circuits if isinstance(circuits, list) else [circuits]
    schedules = [schedule_circuit(circuit, schedule_config, method) for circuit in circuits]
    end_time = time()
    _log_schedule_time(start_time, end_time)
    return schedules[0] if len(schedules) == 1 else schedules
Ejemplo n.º 2
0
def sequence(
    scheduled_circuits: Union[QuantumCircuit, List[QuantumCircuit]],
    backend: Optional[Backend] = None,
    inst_map: Optional[InstructionScheduleMap] = None,
    meas_map: Optional[List[List[int]]] = None,
    dt: Optional[float] = None,
) -> Union[Schedule, List[Schedule]]:
    """
    Schedule a scheduled circuit to a pulse ``Schedule``, using the backend.

    Args:
        scheduled_circuits: Scheduled circuit(s) to be translated
        backend: A backend instance, which contains hardware-specific data required for scheduling
        inst_map: Mapping of circuit operations to pulse schedules. If ``None``, defaults to the
                  ``backend``\'s ``instruction_schedule_map``
        meas_map: List of sets of qubits that must be measured together. If ``None``, defaults to
                  the ``backend``\'s ``meas_map``
        dt: The output sample rate of backend control electronics. For scheduled circuits
            which contain time information, dt is required. If not provided, it will be
            obtained from the backend configuration

    Returns:
        A pulse ``Schedule`` that implements the input circuit

    Raises:
        QiskitError: If ``inst_map`` and ``meas_map`` are not passed and ``backend`` is not passed
    """
    if inst_map is None:
        if backend is None:
            raise QiskitError(
                "Must supply either a backend or inst_map for sequencing.")
        inst_map = backend.defaults().instruction_schedule_map
    if meas_map is None:
        if backend is None:
            raise QiskitError(
                "Must supply either a backend or a meas_map for sequencing.")
        meas_map = backend.configuration().meas_map
    if dt is None:
        if backend is None:
            raise QiskitError(
                "Must supply either a backend or a dt for sequencing.")
        dt = backend.configuration().dt

    schedule_config = ScheduleConfig(inst_map=inst_map,
                                     meas_map=meas_map,
                                     dt=dt)
    circuits = scheduled_circuits if isinstance(
        scheduled_circuits, list) else [scheduled_circuits]
    schedules = [_sequence(circuit, schedule_config) for circuit in circuits]
    return schedules[0] if len(schedules) == 1 else schedules
Ejemplo n.º 3
0
def schedule(
    circuits: Union[QuantumCircuit, List[QuantumCircuit]],
    backend: Optional[BaseBackend] = None,
    inst_map: Optional[InstructionScheduleMap] = None,
    cmd_def: Optional[CmdDef] = None,
    meas_map: Optional[List[List[int]]] = None,
    method: Optional[Union[str, List[str]]] = None
) -> Union[Schedule, List[Schedule]]:
    """
    Schedule a circuit to a pulse ``Schedule``, using the backend, according to any specified
    methods. Supported methods are documented in :py:mod:`qiskit.scheduler.schedule_circuit`.

    Args:
        circuits: The quantum circuit or circuits to translate
        backend: A backend instance, which contains hardware-specific data required for scheduling
        inst_map: Mapping of circuit operations to pulse schedules. If ``None``, defaults to the
                  ``backend``\'s ``instruction_schedule_map``
        cmd_def: Deprecated
        meas_map: List of sets of qubits that must be measured together. If ``None``, defaults to
                  the ``backend``\'s ``meas_map``
        method: Optionally specify a particular scheduling method

    Returns:
        A pulse ``Schedule`` that implements the input circuit

    Raises:
        QiskitError: If ``inst_map`` and ``meas_map`` are not passed and ``backend`` is not passed
    """
    if inst_map is None:
        if cmd_def is not None:
            inst_map = cmd_def
        if backend is None:
            raise QiskitError(
                "Must supply either a backend or InstructionScheduleMap for "
                "scheduling passes.")
        inst_map = backend.defaults().instruction_schedule_map
    if meas_map is None:
        if backend is None:
            raise QiskitError(
                "Must supply either a backend or a meas_map for scheduling passes."
            )
        meas_map = backend.configuration().meas_map

    schedule_config = ScheduleConfig(inst_map=inst_map, meas_map=meas_map)
    circuits = circuits if isinstance(circuits, list) else [circuits]
    schedules = [
        schedule_circuit(circuit, schedule_config, method)
        for circuit in circuits
    ]
    return schedules[0] if len(schedules) == 1 else schedules
Ejemplo n.º 4
0
def schedule(circuits: Union[QuantumCircuit, List[QuantumCircuit]],
             backend: Optional['BaseBackend'] = None,
             cmd_def: Optional[CmdDef] = None,
             meas_map: Optional[List[List[int]]] = None,
             method: Optional[Union[str, List[str]]] = None) -> Union[Schedule, List[Schedule]]:
    """
    Schedule a circuit to a pulse Schedule, using the backend, according to any specified methods.
    Supported methods are documented in
    :py:func:`qiskit.pulse.scheduler.schedule_circuit.schedule_circuit`.

    Args:
        circuits: The quantum circuit or circuits to translate
        backend: A backend instance, which contains hardware specific data required for scheduling
        cmd_def: Mapping of circuit operations to pulse schedules. If None, defaults to the
                 `backend` `cmd_def`
        meas_map: List of sets of qubits that must be measured together. If `None` defaults to
                  the `backend` `meas_map`
        method: Optionally specify a particular scheduling method
    Returns:
        A pulse `Schedule` that implements the input circuit
    Raises:
        QiskitError: If `cmd_def` and `meas_map` are not passed and `backend` is not passed
    """
    if cmd_def is None:
        if backend is None:
            raise QiskitError("Must supply either a backend or CmdDef for scheduling passes.")
        defaults = backend.defaults()
        cmd_def = CmdDef.from_defaults(defaults.cmd_def, defaults.pulse_library)
    if meas_map is None:
        if backend is None:
            raise QiskitError("Must supply either a backend or a meas_map for scheduling passes.")
        meas_map = backend.configuration().meas_map

    schedule_config = ScheduleConfig(cmd_def=cmd_def, meas_map=meas_map)
    circuits = circuits if isinstance(circuits, list) else [circuits]
    schedules = [schedule_circuit(circuit, schedule_config, method) for circuit in circuits]
    return schedules[0] if len(schedules) == 1 else schedules
Ejemplo n.º 5
0
def rabi_schedules(amp_list,
                   qubits,
                   pulse_width,
                   pulse_sigma=None,
                   width_sigma_ratio=4,
                   drives=None,
                   cmd_def=None,
                   meas_map=None):
    """
    Generates schedules for a rabi experiment using a Gaussian pulse

    Args:
        amp_list (list of floats): List of amplitudes for the Gaussian
        pulse [-1,1]
        qubits (list of integers): indices of the qubits to perform a rabi
        pulse_width: width of gaussian (in dt units)
        pulse_sigma: sigma of gaussian
        width_sigma_ratio: set sigma to a certain ratio of the width (use if
        pulse_sigma is None)
        drives: list of DriveChannel objects
        cmd_def: CmdDef object to use
        meas_map: meas_map to use

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

    xdata = amp_list

    # copy the command def
    cmd_def = copy.deepcopy(cmd_def)

    if pulse_sigma is None:
        pulse_sigma = pulse_width / width_sigma_ratio

    # Construct the circuits
    qr = qiskit.QuantumRegister(max(qubits) + 1)
    cr = qiskit.ClassicalRegister(len(qubits))

    circuits = []

    for circ_index, g_amp in enumerate(amp_list):

        circ = qiskit.QuantumCircuit(qr, cr)
        circ.name = 'rabicircuit_%d_0' % circ_index

        rabi_pulse = pulse_lib.gaussian(duration=pulse_width,
                                        amp=g_amp,
                                        sigma=pulse_sigma,
                                        name='rabi_pulse_%d' % circ_index)

        rabi_gate = Gate(name='rabi_%d' % circ_index, num_qubits=1, params=[])

        for _, qubit in enumerate(qubits):

            # add commands to schedule
            schedule = pulse.Schedule(name='rabi_pulse_%f_%d' % (g_amp, qubit))

            schedule += rabi_pulse(drives[qubit])

            # append this schedule to the cmd_def
            cmd_def.add('rabi_%d' % circ_index,
                        qubits=[qubit],
                        schedule=schedule)

            circ.append(rabi_gate, [qr[qubit]])

        for qind, qubit in enumerate(qubits):
            circ.measure(qr[qubit], cr[qind])

        circuits.append(circ)

        # schedule
        schedule_config = ScheduleConfig(cmd_def, meas_map)
        rabi_sched = [
            schedule_circuit(qcirc, schedule_config) for qcirc in circuits
        ]

    return rabi_sched, xdata
Ejemplo n.º 6
0
def drag_schedules(beta_list,
                   qubits,
                   pulse_amp,
                   pulse_width,
                   pulse_sigma=None,
                   width_sigma_ratio=4,
                   drives=None,
                   cmd_def=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: amp of the gaussian (list of length qubits)
        pulse_width: width of gaussian (in dt units)
        pulse_sigma: sigma of gaussian
        width_sigma_ratio: set sigma to a certain ratio of the width (use if
        pulse_sigma is None)
        drives: list of DriveChannel objects
        cmd_def: CmdDef object to use
        meas_map: meas_map to use

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

    xdata = beta_list

    # copy the command def
    cmd_def = copy.deepcopy(cmd_def)

    if pulse_sigma is None:
        pulse_sigma = pulse_width / width_sigma_ratio

    # Construct the circuits
    qr = qiskit.QuantumRegister(max(qubits) + 1)
    cr = qiskit.ClassicalRegister(len(qubits))

    circuits = []

    for circ_index, b_amp in enumerate(beta_list):

        circ = qiskit.QuantumCircuit(qr, cr)
        circ.name = 'dragcircuit_%d_0' % circ_index

        for qind, qubit in enumerate(qubits):

            # positive drag pulse
            drag_pulse = pulse_lib.drag(duration=pulse_width,
                                        amp=pulse_amp[qind],
                                        beta=b_amp,
                                        sigma=pulse_sigma,
                                        name='drag_pulse_%d_%d' %
                                        (circ_index, qubit))

            drag_gate = Gate(name='drag_%d_%d' % (circ_index, qubit),
                             num_qubits=1,
                             params=[])

            # add commands to schedule
            schedule = pulse.Schedule(name='drag_pulse_%f_%d' % (b_amp, qubit))

            schedule += drag_pulse(drives[qubit])

            # append this schedule to the cmd_def
            cmd_def.add('drag_%d_%d' % (circ_index, qubit),
                        qubits=[qubit],
                        schedule=schedule)

            # negative pulse
            drag_pulse2 = pulse_lib.drag(duration=pulse_width,
                                         amp=-1 * pulse_amp[qind],
                                         beta=b_amp,
                                         sigma=pulse_sigma,
                                         name='drag_pulse_%d_%d' %
                                         (circ_index, qubit))

            drag_gate2 = Gate(name='drag2_%d_%d' % (circ_index, qubit),
                              num_qubits=1,
                              params=[])

            # add commands to schedule
            schedule2 = pulse.Schedule(name='drag_pulse2_%f_%d' %
                                       (b_amp, qubit))

            schedule2 += drag_pulse2(drives[qubit])

            # append this schedule to the cmd_def
            cmd_def.add('drag2_%d_%d' % (circ_index, qubit),
                        qubits=[qubit],
                        schedule=schedule2)

            circ.append(drag_gate, [qr[qubit]])
            # circ.u1(np.pi, [qr[qubit]])
            circ.append(drag_gate2, [qr[qubit]])

        for qind, qubit in enumerate(qubits):
            circ.measure(qr[qubit], cr[qind])

        circuits.append(circ)

        # schedule
        schedule_config = ScheduleConfig(cmd_def, meas_map)
        drag_sched = [
            schedule_circuit(qcirc, schedule_config) for qcirc in circuits
        ]

    return drag_sched, xdata