def _assemble_instructions( schedule: Schedule, instruction_converter: InstructionToQobjConverter, run_config: RunConfig, user_pulselib: Dict[str, Command]) -> Tuple[List[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 command), 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, ParametricInstruction): # deprecated instruction = Play(instruction.command, instruction.channels[0], name=instruction.name) if isinstance(instruction, Play) and isinstance( instruction.pulse, ParametricPulse): pulse_shape = ParametricPulseShapes(type(instruction.pulse)).name if pulse_shape not in run_config.parametric_pulses: instruction = Play(instruction.pulse.get_sample_pulse(), instruction.channel, name=instruction.name) if isinstance(instruction, PulseInstruction): # deprecated instruction = Play(SamplePulse( name=name, samples=instruction.command.samples), instruction.channels[0], name=name) if isinstance(instruction, Play) and isinstance( instruction.pulse, SamplePulse): name = hashlib.sha256(instruction.pulse.samples).hexdigest() instruction = Play(SamplePulse(name=name, samples=instruction.pulse.samples), channel=instruction.channel, name=name) user_pulselib[name] = instruction.pulse.samples if isinstance(instruction, (AcquireInstruction, Acquire)): max_memory_slot = max( max_memory_slot, *[slot.index for slot in instruction.mem_slots]) # 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.command)].append(instruction) continue if isinstance(instruction, (DelayInstruction, Delay)): # 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, _), instructions in acquire_instruction_map.items(): qubits, mem_slots, reg_slots = _bundle_channel_indices( instructions) qobj_instructions.append( instruction_converter.convert_single_acquires( time, instructions[0], qubits=qubits, memory_slot=mem_slots, register_slot=reg_slots)) return qobj_instructions, max_memory_slot
def _assemble_instructions( schedule: Schedule, instruction_converter: InstructionToQobjConverter, run_config: RunConfig ) -> Tuple[List[PulseQobjInstruction], Dict[str, Command], int]: """Assembles the instructions in a schedule into a list of PulseQobjInstructions and returns related metadata that will be assembled into the Qobj configuration. Args: schedule: Schedule to assemble. instruction_converter: A converter instance which can convert PulseInstructions to PulseQobjInstructions. run_config: Configuration of the runtime environment. Returns: A list of converted instructions, the user pulse library dictionary (from pulse name to pulse command), and the maximum number of readout memory slots used by this Schedule. """ max_memory_slot = 0 qobj_instructions = [] user_pulselib = {} acquire_instruction_map = defaultdict(list) for time, instruction in schedule.instructions: if isinstance(instruction, ParametricInstruction): pulse_shape = ParametricPulseShapes(type(instruction.command)).name if pulse_shape not in run_config.parametric_pulses: # Convert to SamplePulse if the backend does not support it instruction = PulseInstruction( instruction.command.get_sample_pulse(), instruction.channels[0], name=instruction.name) if isinstance(instruction, PulseInstruction): name = instruction.command.name if name in user_pulselib and instruction.command != user_pulselib[ name]: name = "{0}-{1:x}".format( name, hash(instruction.command.samples.tostring())) instruction = PulseInstruction(command=SamplePulse( name=name, samples=instruction.command.samples), name=instruction.name, channel=instruction.channels[0]) # add samples to pulse library user_pulselib[name] = instruction.command if isinstance(instruction, AcquireInstruction): max_memory_slot = max( max_memory_slot, *[slot.index for slot in instruction.mem_slots]) # 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.command)].append(instruction) continue if isinstance(instruction, DelayInstruction): # 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, _), instructions in acquire_instruction_map.items(): qubits, mem_slots, reg_slots = _bundle_channel_indices( instructions) qobj_instructions.append( instruction_converter.convert_single_acquires( time, instructions[0], qubits=qubits, memory_slot=mem_slots, register_slot=reg_slots)) return qobj_instructions, user_pulselib, max_memory_slot