herutriana44's picture
First Commit
b7d9967 verified
# This code is part of Qiskit.
#
# (C) Copyright IBM 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""
Mapping a scheduled QuantumCircuit to a pulse Schedule.
"""
from collections import defaultdict
from qiskit.circuit.barrier import Barrier
from qiskit.circuit.measure import Measure
from qiskit.circuit.quantumcircuit import QuantumCircuit
from qiskit.exceptions import QiskitError
from qiskit.pulse.schedule import Schedule
from qiskit.pulse.transforms import pad
from qiskit.scheduler.config import ScheduleConfig
from qiskit.scheduler.lowering import lower_gates
def sequence(scheduled_circuit: QuantumCircuit, schedule_config: ScheduleConfig) -> Schedule:
"""
Return the pulse Schedule which implements the input scheduled circuit.
Assume all measurements are done at once at the last of the circuit.
Schedules according to the command definition given by the schedule_config.
Args:
scheduled_circuit: The scheduled quantum circuit to translate.
schedule_config: Backend specific parameters used for building the Schedule.
Returns:
A schedule corresponding to the input ``circuit``.
Raises:
QiskitError: If invalid scheduled circuit is supplied.
"""
circ_pulse_defs = lower_gates(scheduled_circuit, schedule_config)
# find the measurement start time (assume measurement once)
def _meas_start_time():
_qubit_time_available = defaultdict(int)
for instruction in scheduled_circuit.data:
if isinstance(instruction.operation, Measure):
return _qubit_time_available[instruction.qubits[0]]
for q in instruction.qubits:
_qubit_time_available[q] += instruction.operation.duration
return None
meas_time = _meas_start_time()
# restore start times
qubit_time_available = {}
start_times = []
out_circ_pulse_defs = []
for circ_pulse_def in circ_pulse_defs:
active_qubits = [q for q in circ_pulse_def.qubits if q in qubit_time_available]
start_time = max((qubit_time_available[q] for q in active_qubits), default=0)
for q in active_qubits:
if qubit_time_available[q] != start_time:
# print(q, ":", qubit_time_available[q], "!=", start_time)
raise QiskitError("Invalid scheduled circuit.")
stop_time = start_time
if not isinstance(circ_pulse_def.schedule, Barrier):
stop_time += circ_pulse_def.schedule.duration
delay_overlaps_meas = False
for q in circ_pulse_def.qubits:
qubit_time_available[q] = stop_time
if (
meas_time is not None
and circ_pulse_def.schedule.name == "delay"
and stop_time > meas_time
):
qubit_time_available[q] = meas_time
delay_overlaps_meas = True
# skip to delays overlapping measures and barriers
if not delay_overlaps_meas and not isinstance(circ_pulse_def.schedule, Barrier):
start_times.append(start_time)
out_circ_pulse_defs.append(circ_pulse_def)
timed_schedules = [(time, cpd.schedule) for time, cpd in zip(start_times, out_circ_pulse_defs)]
sched = Schedule(*timed_schedules, name=scheduled_circuit.name)
return pad(sched)