def test_shift_unshift(self): """Test shift and then unshifting of schedule""" reference_sched = Schedule() reference_sched += Delay(10, DriveChannel(0)) shifted_sched = reference_sched.shift(10).shift(-10) self.assertEqual(shifted_sched, reference_sched)
def my_test_make_schedule(acquire: int, memoryslot: int, shift: int): op = Acquire(acquire) sched1 = op(AcquireChannel(0), MemorySlot(memoryslot)) sched2 = op(AcquireChannel(1), MemorySlot(memoryslot)).shift(shift) return Schedule(sched1, sched2)
def test_flat_instruction_sequence_returns_empty_list_for_empty_schedule( self): """Test if flat_instruction_sequence returns empty list for empty schedule. """ sched = Schedule() self.assertEqual([], sched.flat_instruction_sequence())
def test_insert_float_time_raises(self): """Test that a floating time will raise an error with insert.""" sched = Schedule() sched += Delay(1, DriveChannel(0)) with self.assertRaises(PulseError): sched.insert(10.1, sched)
def test_different_name_equal(self): """Test that names are ignored when checking equality.""" self.assertEqual(Schedule((0, FrameChange(0, name='fc1')(DriveChannel(1))), name='s1'), Schedule((0, FrameChange(0, name='fc2')(DriveChannel(1))), name='s2'))
def test_truncate_acquisition(self): sched = Schedule(name='test_schedule') sched = sched.insert( 0, Acquire(30, AcquireChannel(1), MemorySlot(1), RegisterSlot(1))) # Check ValueError is not thrown pulse_drawer(sched, plot_range=(0, 15))
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 inst, qubits, _ in scheduled_circuit.data: if isinstance(inst, Measure): return _qubit_time_available[qubits[0]] for q in qubits: _qubit_time_available[q] += inst.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)
def test_different_time_not_equal(self): """Test that not equal if instruction at different time.""" self.assertNotEqual(Schedule((0, FrameChange(0)(DriveChannel(1)))), Schedule((1, FrameChange(0)(DriveChannel(1)))))
def convert_acquire(self, instruction): """Return converted `AcquireInstruction`. Args: instruction (PulseQobjInstruction): acquire qobj Returns: Schedule: Converted and scheduled Instruction """ t0 = instruction.t0 duration = instruction.duration qubits = instruction.qubits qubit_channels = [channels.AcquireChannel(qubit) for qubit in qubits] mem_slots = [ channels.MemorySlot(instruction.memory_slot[i]) for i in range(len(qubits)) ] if hasattr(instruction, 'register_slot'): register_slots = [ channels.RegisterSlot(instruction.register_slot[i]) for i in range(len(qubits)) ] else: register_slots = None discriminators = (instruction.discriminators if hasattr( instruction, 'discriminators') else None) if not isinstance(discriminators, list): discriminators = [discriminators] if any(discriminators[i] != discriminators[0] for i in range(len(discriminators))): warnings.warn( "Can currently only support one discriminator per acquire. Defaulting " "to first discriminator entry.") discriminator = discriminators[0] if discriminator: discriminator = commands.Discriminator( name=discriminators[0].name, params=discriminators[0].params) kernels = (instruction.kernels if hasattr(instruction, 'kernels') else None) if not isinstance(kernels, list): kernels = [kernels] if any(kernels[0] != kernels[i] for i in range(len(kernels))): warnings.warn( "Can currently only support one kernel per acquire. Defaulting to first " "kernel entry.") kernel = kernels[0] if kernel: kernel = commands.Kernel(name=kernels[0].name, params=kernels[0].params) cmd = commands.Acquire(duration, discriminator=discriminator, kernel=kernel) schedule = Schedule() schedule |= commands.AcquireInstruction(cmd, qubit_channels, mem_slots, register_slots) << t0 return schedule
def test_filter_inst_types(self): """Test filtering on instruction types.""" lp0 = self.linear(duration=3, slope=0.2, intercept=0.1) sched = Schedule(name='fake_experiment') sched = sched.insert(0, Play(lp0, self.config.drive(0))) sched = sched.insert(10, Play(lp0, self.config.drive(1))) sched = sched.insert(30, ShiftPhase(-1.57, self.config.drive(0))) sched = sched.insert(40, SetFrequency(8.0, self.config.drive(0))) sched = sched.insert(50, ShiftFrequency(4.0e6, self.config.drive(0))) sched = sched.insert(55, SetPhase(3.14, self.config.drive(0))) for i in range(2): sched = sched.insert( 60, Acquire(5, self.config.acquire(i), MemorySlot(i))) sched = sched.insert(90, Play(lp0, self.config.drive(0))) # test on Acquire only_acquire, no_acquire = \ self._filter_and_test_consistency(sched, instruction_types=[Acquire]) for _, inst in only_acquire.instructions: self.assertIsInstance(inst, Acquire) for _, inst in no_acquire.instructions: self.assertFalse(isinstance(inst, Acquire)) # test two instruction types only_pulse_and_fc, no_pulse_and_fc = \ self._filter_and_test_consistency(sched, instruction_types=[Play, ShiftPhase]) for _, inst in only_pulse_and_fc.instructions: self.assertIsInstance(inst, (Play, ShiftPhase)) for _, inst in no_pulse_and_fc.instructions: self.assertFalse(isinstance(inst, (Play, ShiftPhase))) self.assertEqual(len(only_pulse_and_fc.instructions), 4) self.assertEqual(len(no_pulse_and_fc.instructions), 5) # test on ShiftPhase only_fc, no_fc = \ self._filter_and_test_consistency(sched, instruction_types={ShiftPhase}) self.assertEqual(len(only_fc.instructions), 1) self.assertEqual(len(no_fc.instructions), 8) # test on SetPhase only_setp, no_setp = \ self._filter_and_test_consistency(sched, instruction_types={SetPhase}) self.assertEqual(len(only_setp.instructions), 1) self.assertEqual(len(no_setp.instructions), 8) # test on SetFrequency only_setf, no_setf = self._filter_and_test_consistency( sched, instruction_types=[SetFrequency]) for _, inst in only_setf.instructions: self.assertTrue(isinstance(inst, SetFrequency)) self.assertEqual(len(only_setf.instructions), 1) self.assertEqual(len(no_setf.instructions), 8) # test on ShiftFrequency only_shiftf, no_shiftf = \ self._filter_and_test_consistency(sched, instruction_types=[ShiftFrequency]) for _, inst in only_shiftf.instructions: self.assertTrue(isinstance(inst, ShiftFrequency)) self.assertEqual(len(only_shiftf.instructions), 1) self.assertEqual(len(no_shiftf.instructions), 8)
def align_measures(schedules: Iterable[interfaces.ScheduleComponent], inst_map: Optional[InstructionScheduleMap] = None, cal_gate: str = 'u3', max_calibration_duration: Optional[int] = None, align_time: Optional[int] = None) -> List[Schedule]: """Return new schedules where measurements occur at the same physical time. Minimum measurement wait time (to allow for calibration pulses) is enforced. This is only defined for schedules that are acquire-less or acquire-final per channel: a schedule with pulses or acquires occurring on a channel which has already had a measurement will throw an error. Args: schedules: Collection of schedules to be aligned together inst_map: Mapping of circuit operations to pulse schedules cal_gate: The name of the gate to inspect for the calibration time max_calibration_duration: If provided, inst_map and cal_gate will be ignored align_time: If provided, this will be used as final align time. Returns: The input list of schedules transformed to have their measurements aligned. Raises: PulseError: if an acquire or pulse is encountered on a channel that has already been part of an acquire, or if align_time is negative """ def calculate_align_time(): """Return the the max between the duration of the calibration time and the absolute time of the latest scheduled acquire. """ nonlocal max_calibration_duration if max_calibration_duration is None: max_calibration_duration = get_max_calibration_duration() align_time = max_calibration_duration for schedule in schedules: last_acquire = 0 acquire_times = [ time for time, inst in schedule.instructions if isinstance(inst, (instructions.Acquire, commands.AcquireInstruction)) ] if acquire_times: last_acquire = max(acquire_times) align_time = max(align_time, last_acquire) return align_time def get_max_calibration_duration(): """Return the time needed to allow for readout discrimination calibration pulses.""" max_calibration_duration = 0 for qubits in inst_map.qubits_with_instruction(cal_gate): cmd = inst_map.get(cal_gate, qubits, np.pi, 0, np.pi) max_calibration_duration = max(cmd.duration, max_calibration_duration) return max_calibration_duration if align_time is None and max_calibration_duration is None and inst_map is None: raise exceptions.PulseError( "Must provide a inst_map, an alignment time, " "or a calibration duration.") if align_time is not None and align_time < 0: raise exceptions.PulseError("Align time cannot be negative.") if align_time is None: align_time = calculate_align_time() # Shift acquires according to the new scheduled time new_schedules = [] for schedule in schedules: new_schedule = Schedule(name=schedule.name) acquired_channels = set() measured_channels = set() for time, inst in schedule.instructions: for chan in inst.channels: if isinstance(chan, chans.MeasureChannel): if chan.index in measured_channels: raise exceptions.PulseError( "Multiple measurements are " "not supported by this " "rescheduling pass.") elif chan.index in acquired_channels: raise exceptions.PulseError("Pulse encountered on channel " "{0} after acquire on " "same channel.".format( chan.index)) if isinstance(inst, (instructions.Acquire, commands.AcquireInstruction)): if time > align_time: warnings.warn( "You provided an align_time which is scheduling an acquire " "sooner than it was scheduled for in the original Schedule." ) new_schedule |= inst << align_time acquired_channels.add(inst.channel.index) elif isinstance(inst.channels[0], chans.MeasureChannel): new_schedule |= inst << align_time measured_channels.update({a.index for a in inst.channels}) else: new_schedule |= inst << time new_schedules.append(new_schedule) return new_schedules
def test_filter_intervals(self): """Test filtering on intervals.""" lp0 = self.linear(duration=3, slope=0.2, intercept=0.1) sched = Schedule(name="fake_experiment") sched = sched.insert(0, Play(lp0, self.config.drive(0))) sched = sched.insert(10, Play(lp0, self.config.drive(1))) sched = sched.insert(30, ShiftPhase(-1.57, self.config.drive(0))) for i in range(2): sched = sched.insert( 60, Acquire(5, self.config.acquire(i), MemorySlot(i))) sched = sched.insert(90, Play(lp0, self.config.drive(0))) # split schedule into instructions occurring in (0,13), and those outside filtered, excluded = self._filter_and_test_consistency( sched, time_ranges=((0, 13), )) for start_time, inst in filtered.instructions: self.assertTrue((start_time >= 0) and (start_time + inst.stop_time <= 13)) for start_time, inst in excluded.instructions: self.assertFalse((start_time >= 0) and (start_time + inst.stop_time <= 13)) self.assertEqual(len(filtered.instructions), 2) self.assertEqual(len(excluded.instructions), 4) # split into schedule occurring in and outside of interval (59,65) filtered, excluded = self._filter_and_test_consistency(sched, time_ranges=[ (59, 65) ]) self.assertEqual(len(filtered.instructions), 2) self.assertEqual(filtered.instructions[0][0], 60) self.assertIsInstance(filtered.instructions[0][1], Acquire) self.assertEqual(len(excluded.instructions), 4) self.assertEqual(excluded.instructions[3][0], 90) self.assertIsInstance(excluded.instructions[3][1], Play) # split instructions based on the interval # (none should be, though they have some overlap with some of the instructions) filtered, excluded = self._filter_and_test_consistency(sched, time_ranges=[ (0, 2), (8, 11), (61, 70) ]) self.assertEqual(len(filtered.instructions), 0) self.assertEqual(len(excluded.instructions), 6) # split instructions from multiple non-overlapping intervals, specified # as time ranges filtered, excluded = self._filter_and_test_consistency(sched, time_ranges=[ (10, 15), (63, 93) ]) self.assertEqual(len(filtered.instructions), 2) self.assertEqual(len(excluded.instructions), 4) # split instructions from non-overlapping intervals, specified as Intervals filtered, excluded = self._filter_and_test_consistency(sched, intervals=[ (10, 15), (63, 93) ]) self.assertEqual(len(filtered.instructions), 2) self.assertEqual(len(excluded.instructions), 4)
def test_numpy_integer_input(self): """Test that mixed integer duration types can build a schedule (#5754).""" sched = Schedule() sched += Delay(np.int32(25), DriveChannel(0)) sched += Play(Constant(duration=30, amp=0.1), DriveChannel(0)) self.assertEqual(sched.duration, 55)
def test_different_channels(self): """Test equality is False if different channels.""" self.assertNotEqual(Schedule(FrameChange(0)(DriveChannel(0))), Schedule(FrameChange(0)(DriveChannel(1))))
def convert_acquire(self, instruction): """Return converted `Acquire`. Args: instruction (PulseQobjInstruction): acquire qobj Returns: Schedule: Converted and scheduled Instruction """ t0 = instruction.t0 duration = instruction.duration qubits = instruction.qubits acquire_channels = [channels.AcquireChannel(qubit) for qubit in qubits] mem_slots = [ channels.MemorySlot(instruction.memory_slot[i]) for i in range(len(qubits)) ] if hasattr(instruction, "register_slot"): register_slots = [ channels.RegisterSlot(instruction.register_slot[i]) for i in range(len(qubits)) ] else: register_slots = [None] * len(qubits) discriminators = (instruction.discriminators if hasattr( instruction, "discriminators") else None) if not isinstance(discriminators, list): discriminators = [discriminators] if any(discriminators[i] != discriminators[0] for i in range(len(discriminators))): warnings.warn( "Can currently only support one discriminator per acquire. Defaulting " "to first discriminator entry.") discriminator = discriminators[0] if discriminator: discriminator = Discriminator(name=discriminators[0].name, **discriminators[0].params) kernels = instruction.kernels if hasattr(instruction, "kernels") else None if not isinstance(kernels, list): kernels = [kernels] if any(kernels[0] != kernels[i] for i in range(len(kernels))): warnings.warn( "Can currently only support one kernel per acquire. Defaulting to first " "kernel entry.") kernel = kernels[0] if kernel: kernel = Kernel(name=kernels[0].name, **kernels[0].params) schedule = Schedule() for acquire_channel, mem_slot, reg_slot in zip(acquire_channels, mem_slots, register_slots): schedule |= (instructions.Acquire( duration, acquire_channel, mem_slot=mem_slot, reg_slot=reg_slot, kernel=kernel, discriminator=discriminator, ) << t0) return schedule
def test_same_time_equal(self): """Test equal if instruction at same time.""" self.assertEqual(Schedule((0, FrameChange(0)(DriveChannel(1)))), Schedule((0, FrameChange(0)(DriveChannel(1)))))
def measure(qubits: List[int], backend=None, inst_map: Optional[InstructionScheduleMap] = None, meas_map: Optional[Union[List[List[int]], Dict[int, List[int]]]] = None, qubit_mem_slots: Optional[Dict[int, int]] = None, measure_name: str = 'measure') -> Schedule: """Return a schedule which measures the requested qubits according to the given instruction mapping and measure map, or by using the defaults provided by the backend. By default, the measurement results for each qubit are trivially mapped to the qubit index. This behavior is overridden by qubit_mem_slots. For instance, to measure qubit 0 into MemorySlot(1), qubit_mem_slots can be provided as {0: 1}. Args: qubits: List of qubits to be measured. backend (BaseBackend): 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 ``instruction_schedule_map`` of ``backend``. meas_map: List of sets of qubits that must be measured together. If None, defaults to the ``meas_map`` of ``backend``. qubit_mem_slots: Mapping of measured qubit index to classical bit index. measure_name: Name of the measurement schedule. Returns: A measurement schedule corresponding to the inputs provided. Raises: PulseError: If both ``inst_map`` or ``meas_map``, and ``backend`` is None. """ schedule = Schedule( name="Default measurement schedule for qubits {}".format(qubits)) try: inst_map = inst_map or backend.defaults().instruction_schedule_map meas_map = meas_map or backend.configuration().meas_map except AttributeError: raise exceptions.PulseError( 'inst_map or meas_map, and backend cannot be None simultaneously') if isinstance(meas_map, List): meas_map = utils.format_meas_map(meas_map) measure_groups = set() for qubit in qubits: measure_groups.add(tuple(meas_map[qubit])) for measure_group_qubits in measure_groups: if qubit_mem_slots is not None: unused_mem_slots = set(measure_group_qubits) - set( qubit_mem_slots.values()) try: default_sched = inst_map.get(measure_name, measure_group_qubits) except exceptions.PulseError: raise exceptions.PulseError( "We could not find a default measurement schedule called '{}'. " "Please provide another name using the 'measure_name' keyword " "argument. For assistance, the instructions which are defined are: " "{}".format(measure_name, inst_map.instructions)) for time, inst in default_sched.instructions: if qubit_mem_slots and isinstance( inst, (instructions.Acquire, commands.AcquireInstruction)): if inst.channel.index in qubit_mem_slots: mem_slot = channels.MemorySlot( qubit_mem_slots[inst.channel.index]) else: mem_slot = channels.MemorySlot(unused_mem_slots.pop()) schedule = schedule.insert( time, instructions.Acquire(inst.duration, inst.channel, mem_slot=mem_slot)) elif qubit_mem_slots is None and isinstance( inst, (instructions.Acquire, commands.AcquireInstruction)): schedule = schedule.insert(time, inst) # Measurement pulses should only be added if its qubit was measured by the user elif inst.channels[0].index in qubits: schedule = schedule.insert(time, inst) return schedule
def test_multiple_channels_out_of_order(self): """Test that schedule with multiple channels equal when out of order.""" instructions = [(0, FrameChange(0)(DriveChannel(1))), (1, Acquire(10)(AcquireChannel(0), MemorySlot(1)))] self.assertEqual(Schedule(*instructions), Schedule(*reversed(instructions)))
def setUp(self): self.schedule = Schedule()
def align_measures( schedules: Iterable[Union['Schedule', instructions.Instruction]], inst_map: Optional[InstructionScheduleMap] = None, cal_gate: str = 'u3', max_calibration_duration: Optional[int] = None, align_time: Optional[int] = None, align_all: Optional[bool] = True, ) -> List[Schedule]: """Return new schedules where measurements occur at the same physical time. This transformation will align the first :class:`qiskit.pulse.Acquire` on every channel to occur at the same time. Minimum measurement wait time (to allow for calibration pulses) is enforced and may be set with ``max_calibration_duration``. By default only instructions containing a :class:`~qiskit.pulse.AcquireChannel` or :class:`~qiskit.pulse.MeasureChannel` will be shifted. If you wish to keep the relative timing of all instructions in the schedule set ``align_all=True``. This method assumes that ``MeasureChannel(i)`` and ``AcquireChannel(i)`` correspond to the same qubit and the acquire/play instructions should be shifted together on these channels. .. jupyter-kernel:: python3 :id: align_measures .. jupyter-execute:: from qiskit import pulse from qiskit.pulse import transforms with pulse.build() as sched: with pulse.align_sequential(): pulse.play(pulse.Constant(10, 0.5), pulse.DriveChannel(0)) pulse.play(pulse.Constant(10, 1.), pulse.MeasureChannel(0)) pulse.acquire(20, pulse.AcquireChannel(0), pulse.MemorySlot(0)) sched_shifted = sched << 20 aligned_sched, aligned_sched_shifted = transforms.align_measures([sched, sched_shifted]) assert aligned_sched == aligned_sched_shifted If it is desired to only shift acqusition and measurement stimulus instructions set the flag ``align_all=False``: .. jupyter-execute:: aligned_sched, aligned_sched_shifted = transforms.align_measures( [sched, sched_shifted], align_all=False, ) assert aligned_sched != aligned_sched_shifted Args: schedules: Collection of schedules to be aligned together inst_map: Mapping of circuit operations to pulse schedules cal_gate: The name of the gate to inspect for the calibration time max_calibration_duration: If provided, inst_map and cal_gate will be ignored align_time: If provided, this will be used as final align time. align_all: Shift all instructions in the schedule such that they maintain their relative alignment with the shifted acqusition instruction. If ``False`` only the acqusition and measurement pulse instructions will be shifted. Returns: The input list of schedules transformed to have their measurements aligned. Raises: PulseError: If the provided alignment time is negative. """ def get_first_acquire_times(schedules): """Return a list of first acquire times for each schedule.""" acquire_times = [] for schedule in schedules: visited_channels = set() qubit_first_acquire_times = defaultdict(lambda: None) for time, inst in schedule.instructions: if (isinstance(inst, instructions.Acquire) and inst.channel not in visited_channels): visited_channels.add(inst.channel) qubit_first_acquire_times[inst.channel.index] = time acquire_times.append(qubit_first_acquire_times) return acquire_times def get_max_calibration_duration(inst_map, cal_gate): """Return the time needed to allow for readout discrimination calibration pulses.""" max_calibration_duration = 0 for qubits in inst_map.qubits_with_instruction(cal_gate): cmd = inst_map.get(cal_gate, qubits, np.pi, 0, np.pi) max_calibration_duration = max(cmd.duration, max_calibration_duration) return max_calibration_duration if align_time is not None and align_time < 0: raise exceptions.PulseError("Align time cannot be negative.") first_acquire_times = get_first_acquire_times(schedules) # Extract the maximum acquire in every schedule across all acquires in the schedule. # If there are no acquires in the schedule default to 0. max_acquire_times = [ max(0, *times.values()) for times in first_acquire_times ] if align_time is None: if max_calibration_duration is None: if inst_map: max_calibration_duration = get_max_calibration_duration( inst_map, cal_gate) else: max_calibration_duration = 0 align_time = max(max_calibration_duration, *max_acquire_times) # Shift acquires according to the new scheduled time new_schedules = [] for sched_idx, schedule in enumerate(schedules): new_schedule = Schedule(name=schedule.name, metadata=schedule.metadata) stop_time = schedule.stop_time if align_all: if first_acquire_times[sched_idx]: shift = align_time - max_acquire_times[sched_idx] else: shift = align_time - stop_time else: shift = 0 for time, inst in schedule.instructions: measurement_channels = { chan.index for chan in inst.channels if isinstance(chan, (chans.MeasureChannel, chans.AcquireChannel)) } if measurement_channels: sched_first_acquire_times = first_acquire_times[sched_idx] max_start_time = max(sched_first_acquire_times[chan] for chan in measurement_channels if chan in sched_first_acquire_times) shift = align_time - max_start_time if shift < 0: warnings.warn( "The provided alignment time is scheduling an acquire instruction " "earlier than it was scheduled for in the original Schedule. " "This may result in an instruction being scheduled before t=0 and " "an error being raised.") new_schedule.insert(time + shift, inst, inplace=True) new_schedules.append(new_schedule) return new_schedules
def test_negative_time_raises(self): """Test that a negative time will raise an error.""" sched = Schedule() sched += Delay(1, DriveChannel(0)) with self.assertRaises(PulseError): sched.shift(-10)
def setUp(self): self.schedule = Schedule(name='test_schedule')
def setUp(self): self.schedule = Schedule() self.device = PulseChannelSpec(n_qubits=2, n_control=1, n_registers=2)