Exemplo n.º 1
0
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)
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
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