def test_parametric_pulses_with_no_duplicates(self): """Test parametric pulses with no duplicates.""" schedule = Schedule() drive_channel = DriveChannel(0) schedule += Play(Gaussian(duration=25, sigma=4, amp=0.5j), drive_channel) schedule += Play(Gaussian(duration=25, sigma=4, amp=0.49j), drive_channel) schedule += Play( GaussianSquare(duration=150, amp=0.2, sigma=8, width=140), drive_channel) schedule += Play( GaussianSquare(duration=150, amp=0.19, sigma=8, width=140), drive_channel) schedule += Play(Constant(duration=150, amp=0.1 + 0.4j), drive_channel) schedule += Play(Constant(duration=150, amp=0.1 + 0.41j), drive_channel) schedule += Play(Drag(duration=25, amp=0.2 + 0.3j, sigma=7.8, beta=4), drive_channel) schedule += Play(Drag(duration=25, amp=0.2 + 0.31j, sigma=7.8, beta=4), drive_channel) compressed_schedule = transforms.compress_pulses([schedule]) original_pulse_ids = get_pulse_ids([schedule]) compressed_pulse_ids = get_pulse_ids(compressed_schedule) self.assertEqual(len(original_pulse_ids), len(compressed_pulse_ids))
def test_with_different_channels(self): """Test with different channels.""" schedule = Schedule() schedule += Play(Waveform([0.0, 0.1]), DriveChannel(0)) schedule += Play(Waveform([0.0, 0.1]), DriveChannel(1)) compressed_schedule = transforms.compress_pulses([schedule]) original_pulse_ids = get_pulse_ids([schedule]) compressed_pulse_ids = get_pulse_ids(compressed_schedule) self.assertEqual(len(original_pulse_ids), 2) self.assertEqual(len(compressed_pulse_ids), 1)
def test_sample_pulses_with_tolerance(self): """Test sample pulses with tolerance.""" schedule = Schedule() schedule += Play(Waveform([0.0, 0.1001], epsilon=1e-3), DriveChannel(0)) schedule += Play(Waveform([0.0, 0.1], epsilon=1e-3), DriveChannel(1)) compressed_schedule = transforms.compress_pulses([schedule]) original_pulse_ids = get_pulse_ids([schedule]) compressed_pulse_ids = get_pulse_ids(compressed_schedule) self.assertEqual(len(original_pulse_ids), 2) self.assertEqual(len(compressed_pulse_ids), 1)
def test_no_duplicates(self): """Test with no pulse duplicates.""" schedule = Schedule() drive_channel = DriveChannel(0) schedule += Play(Waveform([0.0, 1.0]), drive_channel) schedule += Play(Waveform([0.0, 0.9]), drive_channel) schedule += Play(Waveform([0.0, 0.3]), drive_channel) compressed_schedule = transforms.compress_pulses([schedule]) original_pulse_ids = get_pulse_ids([schedule]) compressed_pulse_ids = get_pulse_ids(compressed_schedule) self.assertEqual(len(original_pulse_ids), len(compressed_pulse_ids))
def test_with_duplicates(self): """Test compression of schedule.""" schedule = Schedule() drive_channel = DriveChannel(0) schedule += Play(Waveform([0.0, 0.1]), drive_channel) schedule += Play(Waveform([0.0, 0.1]), drive_channel) compressed_schedule = transforms.compress_pulses([schedule]) original_pulse_ids = get_pulse_ids([schedule]) compressed_pulse_ids = get_pulse_ids(compressed_schedule) self.assertEqual(len(compressed_pulse_ids), 1) self.assertEqual(len(original_pulse_ids), 2) self.assertTrue(next(iter(compressed_pulse_ids)) in original_pulse_ids)
def test_sample_pulse_with_clipping(self): """Test sample pulses with clipping.""" schedule = Schedule() drive_channel = DriveChannel(0) schedule += Play(Waveform([0.0, 1.0]), drive_channel) schedule += Play(Waveform([0.0, 1.001], epsilon=1e-3), drive_channel) schedule += Play(Waveform([0.0, 1.0000000001]), drive_channel) compressed_schedule = transforms.compress_pulses([schedule]) original_pulse_ids = get_pulse_ids([schedule]) compressed_pulse_ids = get_pulse_ids(compressed_schedule) self.assertEqual(len(compressed_pulse_ids), 1) self.assertEqual(len(original_pulse_ids), 3) self.assertTrue(next(iter(compressed_pulse_ids)) in original_pulse_ids)
def test_multiple_schedules(self): """Test multiple schedules.""" schedules = [] for _ in range(2): schedule = Schedule() drive_channel = DriveChannel(0) schedule += Play(Waveform([0.0, 0.1]), drive_channel) schedule += Play(Waveform([0.0, 0.1]), drive_channel) schedule += Play(Waveform([0.0, 0.2]), drive_channel) schedules.append(schedule) compressed_schedule = transforms.compress_pulses(schedules) original_pulse_ids = get_pulse_ids(schedules) compressed_pulse_ids = get_pulse_ids(compressed_schedule) self.assertEqual(len(original_pulse_ids), 6) self.assertEqual(len(compressed_pulse_ids), 2)
def _assemble_experiments( schedules: List[Union[pulse.ScheduleComponent, Tuple[int, pulse.ScheduleComponent]]], lo_converter: converters.LoConfigConverter, run_config: RunConfig ) -> Tuple[List[qobj.PulseQobjExperiment], Dict[str, Any]]: """Assembles a list of schedules into PulseQobjExperiments, and returns related metadata that will be assembled into the Qobj configuration. Args: schedules: Schedules to assemble. lo_converter: The configured frequency converter and validator. run_config: Configuration of the runtime environment. Returns: The list of assembled experiments, and the dictionary of related experiment config. Raises: QiskitError: when frequency settings are not compatible with the experiments. """ freq_configs = [ lo_converter(lo_dict) for lo_dict in getattr(run_config, 'schedule_los', []) ] if len(schedules) > 1 and len(freq_configs) not in [0, 1, len(schedules)]: raise QiskitError( 'Invalid frequency setting is specified. If the frequency is specified, ' 'it should be configured the same for all schedules, configured for each ' 'schedule, or a list of frequencies should be provided for a single ' 'frequency sweep schedule.') instruction_converter = getattr(run_config, 'instruction_converter', converters.InstructionToQobjConverter) instruction_converter = instruction_converter(qobj.PulseQobjInstruction, **run_config.to_dict()) schedules = [ sched if isinstance(sched, pulse.Schedule) else pulse.Schedule(sched) for sched in schedules ] compressed_schedules = transforms.compress_pulses(schedules) user_pulselib = {} experiments = [] for idx, schedule in enumerate(compressed_schedules): qobj_instructions, max_memory_slot = _assemble_instructions( schedule, instruction_converter, run_config, user_pulselib) # TODO: add other experimental header items (see circuit assembler) qobj_experiment_header = qobj.QobjExperimentHeader( memory_slots=max_memory_slot + 1, # Memory slots are 0 indexed name=schedule.name or 'Experiment-%d' % idx) experiment = qobj.PulseQobjExperiment(header=qobj_experiment_header, instructions=qobj_instructions) if freq_configs: # This handles the cases where one frequency setting applies to all experiments and # where each experiment has a different frequency freq_idx = idx if len(freq_configs) != 1 else 0 experiment.config = freq_configs[freq_idx] experiments.append(experiment) # Frequency sweep if freq_configs and len(experiments) == 1: experiment = experiments[0] experiments = [] for freq_config in freq_configs: experiments.append( qobj.PulseQobjExperiment(header=experiment.header, instructions=experiment.instructions, config=freq_config)) # Top level Qobj configuration experiment_config = { 'pulse_library': [ qobj.PulseLibraryItem(name=name, samples=samples) for name, samples in user_pulselib.items() ], 'memory_slots': max([exp.header.memory_slots for exp in experiments]) } return experiments, experiment_config
def _assemble_experiments( schedules: List[Union["schedule.ScheduleComponent", Tuple[int, "schedule.ScheduleComponent"]]], lo_converter: converters.LoConfigConverter, run_config: RunConfig, ) -> Tuple[List[qobj.PulseQobjExperiment], Dict[str, Any]]: """Assembles a list of schedules into PulseQobjExperiments, and returns related metadata that will be assembled into the Qobj configuration. Args: schedules: Schedules to assemble. lo_converter: The configured frequency converter and validator. run_config: Configuration of the runtime environment. Returns: The list of assembled experiments, and the dictionary of related experiment config. Raises: QiskitError: when frequency settings are not compatible with the experiments. """ freq_configs = [ lo_converter(lo_dict) for lo_dict in getattr(run_config, "schedule_los", []) ] if len(schedules) > 1 and len(freq_configs) not in [0, 1, len(schedules)]: raise QiskitError( "Invalid 'schedule_los' setting specified. If specified, it should be " "either have a single entry to apply the same LOs for each schedule or " "have length equal to the number of schedules.") instruction_converter = getattr(run_config, "instruction_converter", converters.InstructionToQobjConverter) instruction_converter = instruction_converter(qobj.PulseQobjInstruction, **run_config.to_dict()) formatted_schedules = [ transforms.target_qobj_transform(sched) for sched in schedules ] compressed_schedules = transforms.compress_pulses(formatted_schedules) user_pulselib = {} experiments = [] for idx, sched in enumerate(compressed_schedules): qobj_instructions, max_memory_slot = _assemble_instructions( sched, instruction_converter, run_config, user_pulselib) metadata = sched.metadata if metadata is None: metadata = {} # TODO: add other experimental header items (see circuit assembler) qobj_experiment_header = qobj.QobjExperimentHeader( memory_slots=max_memory_slot + 1, # Memory slots are 0 indexed name=sched.name or "Experiment-%d" % idx, metadata=metadata, ) experiment = qobj.PulseQobjExperiment(header=qobj_experiment_header, instructions=qobj_instructions) if freq_configs: # This handles the cases where one frequency setting applies to all experiments and # where each experiment has a different frequency freq_idx = idx if len(freq_configs) != 1 else 0 experiment.config = freq_configs[freq_idx] experiments.append(experiment) # Frequency sweep if freq_configs and len(experiments) == 1: experiment = experiments[0] experiments = [] for freq_config in freq_configs: experiments.append( qobj.PulseQobjExperiment( header=experiment.header, instructions=experiment.instructions, config=freq_config, )) # Top level Qobj configuration experiment_config = { "pulse_library": [ qobj.PulseLibraryItem(name=name, samples=samples) for name, samples in user_pulselib.items() ], "memory_slots": max(exp.header.memory_slots for exp in experiments), } return experiments, experiment_config