def filter_instructions(sched: Schedule, filters: List[Callable], negate: bool = False, recurse_subroutines: bool = True) -> Schedule: """A filtering function that takes a schedule and returns a schedule consisting of filtered instructions. Args: sched: A pulse schedule to be filtered. filters: List of callback functions that take an instruction and return boolean. negate: Set `True` to accept an instruction if a filter function returns `False`. Otherwise the instruction is accepted when the filter function returns `False`. recurse_subroutines: Set `True` to individually filter instructions inside of a subroutine defined by the :py:class:`~qiskit.pulse.instructions.Call` instruction. Returns: Filtered pulse schedule. """ from qiskit.pulse.transforms import flatten, inline_subroutines target_sched = flatten(sched) if recurse_subroutines: target_sched = inline_subroutines(target_sched) time_inst_tuples = np.array(target_sched.instructions) valid_insts = np.ones(len(time_inst_tuples), dtype=bool) for filt in filters: valid_insts = np.logical_and(valid_insts, np.array(list(map(filt, time_inst_tuples)))) if negate and len(filters) > 0: valid_insts = ~valid_insts return Schedule(*time_inst_tuples[valid_insts], name=sched.name, metadata=sched.metadata)
def test_flatten(self): """Test the flatten transform.""" d0 = pulse.DriveChannel(0) d1 = pulse.DriveChannel(1) schedule = pulse.Schedule() schedule += instructions.Delay(3, d0) grouped = pulse.Schedule() grouped += instructions.Delay(5, d1) grouped += instructions.Delay(7, d0) # include a grouped schedule grouped = schedule + grouped # flatten the schedule inline internal groups flattened = transforms.flatten(grouped) # align all the instructions to the left after flattening flattened = transforms.align_left(flattened) grouped = transforms.align_left(grouped) reference = pulse.Schedule() # d0 reference.insert(0, instructions.Delay(3, d0), inplace=True) reference.insert(3, instructions.Delay(7, d0), inplace=True) # d1 reference.insert(0, instructions.Delay(5, d1), inplace=True) self.assertEqual(flattened, reference) self.assertNotEqual(grouped, reference)
def flatten(self) -> 'Schedule': """Deprecated.""" from qiskit.pulse.transforms import flatten warnings.warn('`This method is being deprecated. Please use ' '`qiskit.pulse.transforms.flatten` function with this schedule.', DeprecationWarning) return flatten(self)
def _update_parameter_table(self, schedule: 'Schedule'): """ Args: schedule: """ # TODO need to fix cyclic import from qiskit.pulse.transforms import flatten schedule = flatten(schedule) for _, inst in schedule.instructions: for param in inst.parameters: self._parameter_table[param].append(inst)
def _apply_filter(self, filter_func: Callable, new_sched_name: str) -> 'Schedule': """Return a Schedule containing only the instructions from this Schedule for which ``filter_func`` returns ``True``. Args: filter_func: Function of the form (int, Union['Schedule', Instruction]) -> bool. new_sched_name: Name of the returned ``Schedule``. """ from qiskit.pulse.transforms import flatten subschedules = flatten(self)._children valid_subschedules = [sched for sched in subschedules if filter_func(sched)] return Schedule(*valid_subschedules, name=new_sched_name)
def load_program(self, program: Union[pulse.Waveform, pulse.ParametricPulse, pulse.Schedule]): """Load a program to draw. Args: program: `Waveform`, `ParametricPulse`, or `Schedule` to draw. Raises: VisualizationError: When input program is invalid data format. """ if isinstance(program, pulse.Schedule): self._schedule_loader(flatten(inline_subroutines(program))) elif isinstance(program, (pulse.Waveform, pulse.ParametricPulse)): self._waveform_loader(program) else: raise VisualizationError('Data type %s is not supported.' % type(program)) # update time range self.set_time_range(0, program.duration, seconds=False) # set title self.fig_title = self.layout['figure_title'](program=program, device=self.device)
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 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()) formatted_schedules = [] for sched in schedules: if isinstance(sched, pulse.Schedule): sched = transforms.inline_subroutines(sched) sched = transforms.flatten(sched) formatted_schedules.append(sched) else: formatted_schedules.append(pulse.Schedule(sched)) 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