Esempio n. 1
0
    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 = ()
Esempio n. 2
0
    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
Esempio n. 3
0
 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
Esempio n. 4
0
 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())
Esempio n. 5
0
 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
Esempio n. 6
0
    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()
Esempio n. 7
0
    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))
Esempio n. 8
0
    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))
Esempio n. 9
0
 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)
Esempio n. 10
0
 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)
Esempio n. 11
0
 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))
Esempio n. 12
0
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__)