Skip to content

Commit

Permalink
Fixes Qiskit#7078: Add is_schedulable property to qiskit.pulse.Channe…
Browse files Browse the repository at this point in the history
…l and don't apply a delay to it if True

RegisterSlot and MemorySlot have this set to False. The default implementation in Channel sets it to True.
  • Loading branch information
pollyshaw committed Jul 19, 2022
1 parent 3395b5e commit 9bf6e09
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 24 deletions.
15 changes: 15 additions & 0 deletions qiskit/pulse/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ def name(self) -> str:
"""Return the shorthand alias for this channel, which is based on its type and index."""
return f"{self.__class__.prefix}{self._index}"

@property
def is_schedulable(self) -> bool:
"""Return whether this channel can be independently scheduled"""
return True

def __repr__(self):
return f"{self.__class__.__name__}({self._index})"

Expand Down Expand Up @@ -213,10 +218,20 @@ class MemorySlot(ClassicalIOChannel):

prefix = "m"

@property
def is_schedulable(self) -> bool:
"""Return whether this channel can be independently scheduled"""
return False


class RegisterSlot(ClassicalIOChannel):
"""Classical resister slot channels represent classical registers (low-latency classical
memory).
"""

prefix = "c"

@property
def is_schedulable(self) -> bool:
"""Return whether this channel can be independently scheduled"""
return False
9 changes: 2 additions & 7 deletions qiskit/pulse/instructions/acquire.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,9 @@ def channel(self) -> AcquireChannel:
return self.operands[1]

@property
def channels(self) -> Tuple[AcquireChannel]:
def channels(self) -> Tuple[Union[AcquireChannel, MemorySlot, RegisterSlot]]:
"""Returns the channels that this schedule uses."""
return (self.channel,)

@property
def slots(self) -> Tuple[Union[MemorySlot, RegisterSlot]]:
"""Returns the slots that this schedule uses."""
return tuple(self.operands[ind] for ind in (2, 3) if self.operands[ind] is not None)
return tuple(self.operands[ind] for ind in (1, 2, 3) if self.operands[ind] is not None)

@property
def duration(self) -> Union[int, ParameterExpression]:
Expand Down
5 changes: 0 additions & 5 deletions qiskit/pulse/instructions/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,6 @@ def start_time(self) -> int:
"""Relative begin time of this instruction."""
return 0

@property
def slots(self) -> Tuple[Channel]:
"""Returns any slots that this schedule uses"""
return ()

@property
def stop_time(self) -> int:
"""Relative end time of this instruction."""
Expand Down
10 changes: 3 additions & 7 deletions qiskit/pulse/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,9 +523,7 @@ def _add_timeslots(self, time: int, schedule: "ScheduleComponent") -> None:
other_timeslots = _get_timeslots(schedule)
self._duration = max(self._duration, time + schedule.duration)

for channel in schedule.channels + (
schedule.slots if isinstance(schedule, Instruction) else ()
):
for channel in schedule.channels:
if channel not in self._timeslots:
if time == 0:
self._timeslots[channel] = copy.copy(other_timeslots[channel])
Expand Down Expand Up @@ -577,9 +575,7 @@ def _remove_timeslots(self, time: int, schedule: "ScheduleComponent"):
if not isinstance(time, int):
raise PulseError("Schedule start time must be an integer.")

for channel in schedule.channels + (
schedule.slots if isinstance(schedule, Instruction) else ()
):
for channel in schedule.channels:

if channel not in self._timeslots:
raise PulseError(f"The channel {channel} is not present in the schedule")
Expand Down Expand Up @@ -1499,7 +1495,7 @@ def _get_timeslots(schedule: "ScheduleComponent") -> TimeSlots:
if isinstance(schedule, Instruction):
duration = schedule.duration
instruction_duration_validation(duration)
timeslots = {channel: [(0, duration)] for channel in schedule.channels + schedule.slots}
timeslots = {channel: [(0, duration)] for channel in schedule.channels}
elif isinstance(schedule, Schedule):
timeslots = schedule.timeslots
else:
Expand Down
8 changes: 3 additions & 5 deletions qiskit/scheduler/lowering.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
from qiskit.circuit.measure import Measure
from qiskit.circuit.quantumcircuit import QuantumCircuit
from qiskit.exceptions import QiskitError
from qiskit.pulse import Schedule, Acquire
from qiskit.pulse import Schedule
from qiskit.pulse import instructions as pulse_inst
from qiskit.pulse.channels import AcquireChannel, DriveChannel
from qiskit.pulse.channels import AcquireChannel, MemorySlot, DriveChannel
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.macros import measure
from qiskit.scheduler.config import ScheduleConfig
Expand Down Expand Up @@ -79,9 +79,7 @@ def get_measure_schedule(qubit_mem_slots: Dict[int, int]) -> CircuitPulseDef:
meas_q = target_qobj_transform(meas_q)
acquire_q = meas_q.filter(channels=[AcquireChannel(qubit)])
mem_slot_index = [
acquire[1].mem_slot.index
for acquire in acquire_q.instructions
if isinstance(acquire[1], Acquire) and not (acquire[1].mem_slot is None)
chan.index for chan in acquire_q.channels if isinstance(chan, MemorySlot)
][0]
if mem_slot_index != qubit_mem_slots[qubit]:
raise KeyError(
Expand Down

0 comments on commit 9bf6e09

Please sign in to comment.