def __init__(self, name: str = None, start_time: int = 0): """Create empty schedule. Args: name (str, optional): Name of this schedule. Defaults to None. start_time (int, optional): Begin time of this schedule. Defaults to 0. """ self._name = name self._start_time = start_time self._occupancy = TimeslotCollection(timeslots=[]) self._children = ()
def __init__(self, command: Acquire, qubits: Union[Qubit, List[Qubit]], mem_slots: Union[MemorySlot, List[MemorySlot]], reg_slots: Union[RegisterSlot, List[RegisterSlot]] = None, start_time: int = 0): if isinstance(qubits, Qubit): qubits = [qubits] if mem_slots: if isinstance(mem_slots, MemorySlot): mem_slots = [mem_slots] elif len(qubits) != len(mem_slots): raise PulseError("#mem_slots must be equals to #qubits") if reg_slots: if isinstance(reg_slots, RegisterSlot): reg_slots = [reg_slots] if len(qubits) != len(reg_slots): raise PulseError("#reg_slots must be equals to #qubits") else: reg_slots = [] # TODO: more precise time-slots slots = [ Timeslot(Interval(0, command.duration), q.acquire) for q in qubits ] slots.extend([ Timeslot(Interval(0, command.duration), mem) for mem in mem_slots ]) super().__init__(command, start_time, TimeslotCollection(slots)) self._qubits = qubits self._mem_slots = mem_slots self._reg_slots = reg_slots
def __init__(self, command: PersistentValue, channel: OutputChannel, start_time: int = 0): slots = [Timeslot(Interval(start_time, start_time), channel)] super().__init__(command, start_time, TimeslotCollection(slots)) self._channel = channel
def test_empty_schedule(self): """Test empty schedule.""" sched = Schedule() self.assertEqual(0, sched.start_time) self.assertEqual(0, sched.stop_time) self.assertEqual(0, sched.duration) self.assertEqual((), sched.children) self.assertEqual(TimeslotCollection([]), sched.occupancy) self.assertEqual([], sched.flat_instruction_sequence())
def __init__(self, command: SamplePulse, channel: OutputChannel, start_time: int = 0): slots = [ Timeslot(Interval(start_time, start_time + command.duration), channel) ] super().__init__(command, start_time, TimeslotCollection(slots)) self._channel = channel
def __init__(self, label: str, snap_type: str, start_time: int = 0): """Create new snapshot command. Args: label (str): Snapshot label which is used to identify the snapshot in the output. snap_type (str): Type of snapshot, e.g., “state” (take a snapshot of the quantum state). The types of snapshots offered are defined in a separate specification document for simulators. start_time (int, optional): Begin time of snapshot. Defaults to 0. """ PulseCommand.__init__(self, duration=0) Instruction.__init__(self, self, start_time, TimeslotCollection([])) self._label = label self._type = snap_type self._channel = SnapshotChannel()
def test_empty_collection(self): """Test empty collection creation and its operations. """ empty = TimeslotCollection([]) self.assertEqual(True, empty.is_mergeable_with(empty)) # can merge with normal collection normal = TimeslotCollection([Timeslot(Interval(1, 3), AcquireChannel(0)), Timeslot(Interval(3, 5), AcquireChannel(0))]) self.assertEqual(True, empty.is_mergeable_with(normal)) self.assertEqual(normal, empty.merged(normal))
def test_can_merge_two_mergeable_collections(self): """Test if merge two mergeable time-slot collections. """ # same interval but different channel col1 = TimeslotCollection([Timeslot(Interval(1, 3), AcquireChannel(0))]) col2 = TimeslotCollection([Timeslot(Interval(1, 3), AcquireChannel(1))]) self.assertEqual(True, col1.is_mergeable_with(col2)) expected = TimeslotCollection([Timeslot(Interval(1, 3), AcquireChannel(0)), Timeslot(Interval(1, 3), AcquireChannel(1))]) self.assertEqual(expected, col1.merged(col2)) # same channel but different interval col1 = TimeslotCollection([Timeslot(Interval(1, 3), AcquireChannel(0))]) col2 = TimeslotCollection([Timeslot(Interval(3, 5), AcquireChannel(0))]) self.assertEqual(True, col1.is_mergeable_with(col2)) expected = TimeslotCollection([Timeslot(Interval(1, 3), AcquireChannel(0)), Timeslot(Interval(3, 5), AcquireChannel(0))]) self.assertEqual(expected, col1.merged(col2))
def test_can_create_with_valid_timeslots(self): """Test valid time-slot collection creation without error. """ slots = [Timeslot(Interval(1, 3), AcquireChannel(0)), Timeslot(Interval(3, 5), AcquireChannel(0))] TimeslotCollection(slots)
def test_shifted(self): """Test if `shifted` shifts the collection for specified time. """ actual = TimeslotCollection([Timeslot(Interval(1, 3), AcquireChannel(0))]).shifted(10) expected = TimeslotCollection([Timeslot(Interval(11, 13), AcquireChannel(0))]) self.assertEqual(expected, actual)
def test_unmergeable_collections(self): """Test if return false for unmergeable collections. """ col1 = TimeslotCollection([Timeslot(Interval(1, 3), AcquireChannel(0))]) col2 = TimeslotCollection([Timeslot(Interval(2, 4), AcquireChannel(0))]) self.assertEqual(False, col1.is_mergeable_with(col2))
class Schedule(ScheduleComponent): """Schedule of instructions. The composite node of a schedule tree.""" def __init__(self, name: str = None, start_time: int = 0): """Create empty schedule. Args: name (str, optional): Name of this schedule. Defaults to None. start_time (int, optional): Begin time of this schedule. Defaults to 0. """ self._name = name self._start_time = start_time self._occupancy = TimeslotCollection(timeslots=[]) self._children = () @property def name(self) -> str: """Name of this schedule.""" return self._name def insert(self, start_time: int, schedule: ScheduleComponent) -> 'Schedule': """Return a new schedule with inserting a `schedule` at `start_time`. Args: start_time (int): time to be inserted schedule (ScheduleComponent): schedule to be inserted Returns: Schedule: a new schedule inserted a `schedule` at `start_time` Raises: PulseError: when an invalid schedule is specified or failed to insert """ if not isinstance(schedule, ScheduleComponent): raise PulseError("Invalid to be inserted: %s" % schedule.__class__.__name__) news = copy(self) try: news._insert(start_time, schedule) except PulseError as err: raise PulseError(err.message) return news def _insert(self, start_time: int, schedule: ScheduleComponent): """Insert a new `schedule` at `start_time`. Args: start_time (int): start time of the schedule schedule (ScheduleComponent): schedule to be inserted Raises: PulseError: when an invalid schedule is specified or failed to insert """ if schedule == self: raise PulseError("Cannot insert self to avoid infinite recursion") shifted = schedule.occupancy.shifted(start_time) if self._occupancy.is_mergeable_with(shifted): self._occupancy = self._occupancy.merged(shifted) self._children += (schedule.shifted(start_time), ) else: logger.warning("Fail to insert %s at %s due to timing overlap", schedule, start_time) raise PulseError("Fail to insert %s at %s due to overlap" % (str(schedule), start_time)) def append(self, schedule: ScheduleComponent) -> 'Schedule': """Return a new schedule with appending a `schedule` at the timing just after the last instruction finishes. Args: schedule (ScheduleComponent): schedule to be appended Returns: Schedule: a new schedule appended a `schedule` Raises: PulseError: when an invalid schedule is specified or failed to append """ if not isinstance(schedule, ScheduleComponent): raise PulseError("Invalid to be appended: %s" % schedule.__class__.__name__) news = copy(self) try: news._insert(self.stop_time, schedule) except PulseError: logger.warning("Fail to append %s due to timing overlap", schedule) raise PulseError("Fail to append %s due to overlap" % str(schedule)) return news @property def duration(self) -> int: return self.stop_time - self.start_time @property def occupancy(self) -> TimeslotCollection: return self._occupancy def shifted(self, shift: int) -> ScheduleComponent: news = copy(self) news._start_time += shift news._occupancy = self._occupancy.shifted(shift) return news @property def start_time(self) -> int: return self._occupancy.start_time(default=self._start_time) @property def stop_time(self) -> int: return self._occupancy.stop_time(default=self._start_time) @property def children(self) -> Tuple[ScheduleComponent, ...]: return self._children def __add__(self, schedule: ScheduleComponent): return self.append(schedule) def __or__(self, schedule: ScheduleComponent): return self.insert(0, schedule) def __str__(self): res = "Schedule(%s):\n" % (self._name or "") instructions = sorted(self.flat_instruction_sequence(), key=attrgetter("start_time")) res += '\n'.join([str(i) for i in instructions]) return res def flat_instruction_sequence(self) -> List[Instruction]: """Return instruction sequence of this schedule. Each instruction has absolute start time. """ return [_ for _ in Schedule._flatten_generator(self)] @staticmethod def _flatten_generator(node: ScheduleComponent, time: int = 0): if isinstance(node, Schedule): for child in node.children: yield from Schedule._flatten_generator(child, time + node._start_time) elif isinstance(node, Instruction): yield node.shifted(time) else: raise PulseError("Unknown ScheduleComponent type: %s" % node.__class__.__name__)