def test_snapshot(self): """Test converted qobj from Snapshot.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = Snapshot(label='label', snapshot_type='type') valid_qobj = PulseQobjInstruction(name='snapshot', t0=0, label='label', type='type') self.assertEqual(converter(0, instruction), valid_qobj)
def test_deprecated_drive_instruction(self): """Test converted qobj from PulseInstruction.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) with self.assertWarns(DeprecationWarning): command = SamplePulse(np.arange(0, 0.01), name='linear') with self.assertWarns(DeprecationWarning): instruction = command(DriveChannel(0)) valid_qobj = PulseQobjInstruction(name='linear', ch='d0', t0=0) self.assertEqual(converter(0, instruction), valid_qobj)
def test_set_frequency(self): """Test converted qobj from SetFrequency.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = SetFrequency(8.0e9, DriveChannel(0)) valid_qobj = PulseQobjInstruction(name='setf', ch='d0', t0=0, frequency=8.0) self.assertEqual(converter(0, instruction), valid_qobj)
def test_set_phase(self): """Test converted qobj from FrameChangeInstruction.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = SetPhase(3.14, DriveChannel(0)) valid_qobj = PulseQobjInstruction(name='setp', ch='d0', t0=0, phase=3.14) self.assertEqual(converter(0, instruction), valid_qobj)
def test_gaussian_square_pulse_instruction(self): """Test that parametric pulses are correctly converted to PulseQobjInstructions.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = Play(GaussianSquare(duration=1500, sigma=15, amp=-0.5 + 0.2j, width=1300), MeasureChannel(1)) valid_qobj = PulseQobjInstruction( name='parametric_pulse', pulse_shape='gaussian_square', ch='m1', t0=10, parameters={'duration': 1500, 'sigma': 15, 'amp': -0.5 + 0.2j, 'width': 1300}) self.assertEqual(converter(10, instruction), valid_qobj)
def test_drive_instruction(self): """Test converted qobj from PulseInstruction.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) command = SamplePulse(np.arange(0, 0.01), name='linear') instruction = command(self.device.q[0].drive) valid_qobj = PulseQobjInstruction( name='linear', ch='d0', t0=0 ) self.assertEqual(converter(0, instruction), valid_qobj)
def test_persistent_value(self): """Test converted qobj from PersistentValueInstruction.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) with self.assertWarns(DeprecationWarning): command = PersistentValue(value=0.1j) with self.assertWarns(DeprecationWarning): instruction = command(DriveChannel(0)) valid_qobj = PulseQobjInstruction(name='pv', ch='d0', t0=0, val=0.1j) with self.assertWarns(DeprecationWarning): self.assertEqual(converter(0, instruction), valid_qobj)
def test_deprecated_gaussian_pulse_instruction(self): """Test that parametric pulses are correctly converted to PulseQobjInstructions.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) with self.assertWarns(DeprecationWarning): instruction = Gaussian(duration=25, sigma=15, amp=-0.5 + 0.2j)(DriveChannel(0)) valid_qobj = PulseQobjInstruction( name='parametric_pulse', pulse_shape='gaussian', ch='d0', t0=0, parameters={'duration': 25, 'sigma': 15, 'amp': -0.5 + 0.2j}) self.assertEqual(converter(0, instruction), valid_qobj)
def test_persistent_value(self): """Test converted qobj from PersistentValueInstruction.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) command = PersistentValue(value=0.1j) instruction = command(self.device.q[0].drive) valid_qobj = PulseQobjInstruction( name='pv', ch='d0', t0=0, val=0.1j ) self.assertEqual(converter(0, instruction), valid_qobj)
def test_frame_change(self): """Test converted qobj from FrameChangeInstruction.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) command = FrameChange(phase=0.1) instruction = command(self.device.q[0].drive) valid_qobj = PulseQobjInstruction( name='fc', ch='d0', t0=0, phase=0.1 ) self.assertEqual(converter(0, instruction), valid_qobj)
def test_frame_change(self): """Test converted qobj from FrameChangeInstruction.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) with self.assertWarns(DeprecationWarning): command = FrameChange(phase=0.1) with self.assertWarns(DeprecationWarning): instruction = command(DriveChannel(0)) valid_qobj = PulseQobjInstruction(name='fc', ch='d0', t0=0, phase=0.1) self.assertEqual(converter(0, instruction), valid_qobj) instruction = ShiftPhase(0.1, DriveChannel(0)) self.assertEqual(converter(0, instruction), valid_qobj)
def test_constant_pulse_instruction(self): """Test that parametric pulses are correctly converted to PulseQobjInstructions.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = Play(Constant(duration=25, amp=1), ControlChannel(2)) valid_qobj = PulseQobjInstruction(name='parametric_pulse', pulse_shape='constant', ch='u2', t0=20, parameters={ 'duration': 25, 'amp': 1 }) self.assertEqual(converter(20, instruction), valid_qobj)
def test_constant_pulse_instruction(self): """Test that parametric pulses are correctly converted to PulseQobjInstructions.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = Play(Constant(duration=25, amp=1), ControlChannel(2)) valid_qobj = PulseQobjInstruction( name="parametric_pulse", pulse_shape="constant", ch="u2", t0=20, parameters={ "duration": 25, "amp": 1 }, ) self.assertEqual(converter(20, instruction), valid_qobj)
def test_gaussian_pulse_instruction(self): """Test that parametric pulses are correctly converted to PulseQobjInstructions.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = Play(Gaussian(duration=25, sigma=15, amp=-0.5 + 0.2j), DriveChannel(0)) valid_qobj = PulseQobjInstruction( name="parametric_pulse", pulse_shape="gaussian", ch="d0", t0=0, parameters={ "duration": 25, "sigma": 15, "amp": -0.5 + 0.2j }, ) self.assertEqual(converter(0, instruction), valid_qobj)
def test_drag_pulse_instruction(self): """Test that parametric pulses are correctly converted to PulseQobjInstructions.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = Drag(duration=25, sigma=15, amp=-0.5 + 0.2j, beta=0.5)(DriveChannel(0)) valid_qobj = PulseQobjInstruction(name='parametric_pulse', pulse_shape='drag', ch='d0', t0=30, parameters={ 'duration': 25, 'sigma': 15, 'amp': -0.5 + 0.2j, 'beta': 0.5 }) self.assertEqual(converter(30, instruction), valid_qobj)
def test_acquire(self): """Test converted qobj from AcquireInstruction.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = Acquire(10, AcquireChannel(0), MemorySlot(0), RegisterSlot(0)) valid_qobj = PulseQobjInstruction(name='acquire', t0=0, duration=10, qubits=[0], memory_slot=[0], register_slot=[0]) self.assertEqual(converter(0, instruction), valid_qobj) # without register instruction = Acquire(10, AcquireChannel(0), MemorySlot(0)) valid_qobj = PulseQobjInstruction(name='acquire', t0=0, duration=10, qubits=[0], memory_slot=[0]) self.assertEqual(converter(0, instruction), valid_qobj)
def test_gaussian_square_pulse_instruction(self): """Test that parametric pulses are correctly converted to PulseQobjInstructions.""" converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2) instruction = Play( GaussianSquare(duration=1500, sigma=15, amp=-0.5 + 0.2j, width=1300), MeasureChannel(1)) valid_qobj = PulseQobjInstruction( name="parametric_pulse", pulse_shape="gaussian_square", ch="m1", t0=10, parameters={ "duration": 1500, "sigma": 15, "amp": -0.5 + 0.2j, "width": 1300 }, ) self.assertEqual(converter(10, instruction), valid_qobj)
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 _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
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): 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)): # 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