def test_play_sample_pulse(self): """Test play instruction with sample pulse.""" d0 = pulse.DriveChannel(0) test_pulse = library.Waveform([0.0, 0.0]) with pulse.build() as schedule: pulse.play(test_pulse, d0) reference = pulse.Schedule() reference += instructions.Play(test_pulse, d0) self.assertEqual(schedule, reference)
def test_play(self): """Test basic play instruction.""" duration = 4 pulse = library.Waveform([1.0] * duration, name='test') play = instructions.Play(pulse, channels.DriveChannel(1)) self.assertIsInstance(play.id, int) self.assertEqual(play.name, pulse.name) self.assertEqual(play.duration, duration) self.assertEqual(repr(play), "Play(Waveform(array([1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j]), name='test')," " DriveChannel(1), name='test')")
def _read_waveform(file_obj, version): header = formats.WAVEFORM._make( struct.unpack( formats.WAVEFORM_PACK, file_obj.read(formats.WAVEFORM_SIZE), )) samples_raw = file_obj.read(header.data_size) samples = common.data_from_binary(samples_raw, np.load) name = value.read_value(file_obj, version, {}) return library.Waveform( samples=samples, name=name, epsilon=header.epsilon, limit_amplitude=header.amp_limited, )
def bind_pulse(self, pulse): """Bind the supplied pulse to a converter method by pulse name. Args: pulse (PulseLibraryItem): Pulse to bind """ pulse = library.Waveform(pulse.samples, pulse.name) @self.bind_name(pulse.name) def convert_named_drive(self, instruction): """Return converted `Play`. Args: instruction (PulseQobjInstruction): pulse qobj Returns: Schedule: Converted and scheduled pulse """ t0 = instruction.t0 channel = self.get_channel(instruction.ch) return instructions.Play(pulse, channel) << t0
def _assemble_instructions( schedule: pulse.Schedule, instruction_converter: converters.InstructionToQobjConverter, run_config: RunConfig, user_pulselib: Dict[str, List[complex]] ) -> Tuple[List[qobj.PulseQobjInstruction], int]: """Assembles the instructions in a schedule into a list of PulseQobjInstructions and returns related metadata that will be assembled into the Qobj configuration. Lookup table for pulses defined in all experiments are registered in ``user_pulselib``. This object should be mutable python dictionary so that items are properly updated after each instruction assemble. The dictionary is not returned to avoid redundancy. Args: schedule: Schedule to assemble. instruction_converter: A converter instance which can convert PulseInstructions to PulseQobjInstructions. run_config: Configuration of the runtime environment. user_pulselib: User pulse library from previous schedule. Returns: A list of converted instructions, the user pulse library dictionary (from pulse name to pulse samples), and the maximum number of readout memory slots used by this Schedule. """ max_memory_slot = 0 qobj_instructions = [] acquire_instruction_map = defaultdict(list) for time, instruction in schedule.instructions: if (isinstance(instruction, instructions.Play) and isinstance(instruction.pulse, library.ParametricPulse)): pulse_shape = ParametricPulseShapes(type(instruction.pulse)).name if pulse_shape not in run_config.parametric_pulses: instruction = instructions.Play( instruction.pulse.get_waveform(), instruction.channel, name=instruction.name) if (isinstance(instruction, instructions.Play) and isinstance(instruction.pulse, library.Waveform)): name = hashlib.sha256(instruction.pulse.samples).hexdigest() instruction = instructions.Play(library.Waveform( name=name, samples=instruction.pulse.samples), channel=instruction.channel, name=name) user_pulselib[name] = instruction.pulse.samples if isinstance(instruction, instructions.Acquire): if instruction.mem_slot: max_memory_slot = max(max_memory_slot, instruction.mem_slot.index) # Acquires have a single AcquireChannel per inst, but we have to bundle them # together into the Qobj as one instruction with many channels acquire_instruction_map[(time, instruction.duration)].append(instruction) continue if isinstance(instruction, (instructions.Delay, instructions.Directive)): # delay instructions are ignored as timing is explicit within qobj continue qobj_instructions.append(instruction_converter(time, instruction)) if acquire_instruction_map: if hasattr(run_config, 'meas_map'): _validate_meas_map(acquire_instruction_map, run_config.meas_map) for (time, _), instrs in acquire_instruction_map.items(): qobj_instructions.append( instruction_converter.convert_bundled_acquires(time, instrs), ) return qobj_instructions, max_memory_slot
def setUp(self): """Setup play tests.""" super().setUp() self.duration = 4 self.pulse_op = library.Waveform([1.0] * self.duration, name="test")
def _assemble_instructions( sched: Union[pulse.Schedule, pulse.ScheduleBlock], instruction_converter: converters.InstructionToQobjConverter, run_config: RunConfig, user_pulselib: Dict[str, List[complex]], ) -> Tuple[List[qobj.PulseQobjInstruction], int]: """Assembles the instructions in a schedule into a list of PulseQobjInstructions and returns related metadata that will be assembled into the Qobj configuration. Lookup table for pulses defined in all experiments are registered in ``user_pulselib``. This object should be mutable python dictionary so that items are properly updated after each instruction assemble. The dictionary is not returned to avoid redundancy. Args: sched: Schedule to assemble. instruction_converter: A converter instance which can convert PulseInstructions to PulseQobjInstructions. run_config: Configuration of the runtime environment. user_pulselib: User pulse library from previous schedule. Returns: A list of converted instructions, the user pulse library dictionary (from pulse name to pulse samples), and the maximum number of readout memory slots used by this Schedule. """ sched = transforms.target_qobj_transform(sched) max_memory_slot = 0 qobj_instructions = [] acquire_instruction_map = defaultdict(list) for time, instruction in sched.instructions: if isinstance(instruction, instructions.Play): if isinstance(instruction.pulse, (library.ParametricPulse, library.SymbolicPulse)): is_backend_supported = True try: pulse_shape = ParametricPulseShapes(type(instruction.pulse)).name if pulse_shape not in run_config.parametric_pulses: is_backend_supported = False except ValueError: # Custom pulse class, or bare SymbolicPulse object. is_backend_supported = False if not is_backend_supported: instruction = instructions.Play( instruction.pulse.get_waveform(), instruction.channel, name=instruction.name ) if isinstance(instruction.pulse, library.Waveform): name = hashlib.sha256(instruction.pulse.samples).hexdigest() instruction = instructions.Play( library.Waveform(name=name, samples=instruction.pulse.samples), channel=instruction.channel, name=name, ) user_pulselib[name] = instruction.pulse.samples # ignore explicit delay instrs on acq channels as they are invalid on IBMQ backends; # timing of other instrs will still be shifted appropriately if isinstance(instruction, instructions.Delay) and isinstance( instruction.channel, channels.AcquireChannel ): continue if isinstance(instruction, instructions.Acquire): if instruction.mem_slot: max_memory_slot = max(max_memory_slot, instruction.mem_slot.index) # Acquires have a single AcquireChannel per inst, but we have to bundle them # together into the Qobj as one instruction with many channels acquire_instruction_map[(time, instruction.duration)].append(instruction) continue qobj_instructions.append(instruction_converter(time, instruction)) if acquire_instruction_map: if hasattr(run_config, "meas_map"): _validate_meas_map(acquire_instruction_map, run_config.meas_map) for (time, _), instrs in acquire_instruction_map.items(): qobj_instructions.append( instruction_converter.convert_bundled_acquires(time, instrs), ) return qobj_instructions, max_memory_slot