Ejemplo n.º 1
0
def _assemble_config(
    lo_converter: converters.LoConfigConverter,
    experiment_config: Dict[str, Any],
    run_config: RunConfig,
) -> qobj.PulseQobjConfig:
    """Assembles the QobjConfiguration from experimental config and runtime config.

    Args:
        lo_converter: The configured frequency converter and validator.
        experiment_config: Schedules to assemble.
        run_config: Configuration of the runtime environment.

    Returns:
        The assembled PulseQobjConfig.
    """
    qobj_config = run_config.to_dict()
    qobj_config.update(experiment_config)

    # Run config not needed in qobj config
    qobj_config.pop("meas_map", None)
    qobj_config.pop("qubit_lo_range", None)
    qobj_config.pop("meas_lo_range", None)

    # convert enums to serialized values
    meas_return = qobj_config.get("meas_return", "avg")
    if isinstance(meas_return, qobj_utils.MeasReturnType):
        qobj_config["meas_return"] = meas_return.value

    meas_level = qobj_config.get("meas_level", 2)
    if isinstance(meas_level, qobj_utils.MeasLevel):
        qobj_config["meas_level"] = meas_level.value

    # convert LO frequencies to GHz
    qobj_config["qubit_lo_freq"] = [
        freq / 1e9 for freq in qobj_config["qubit_lo_freq"]
    ]
    qobj_config["meas_lo_freq"] = [
        freq / 1e9 for freq in qobj_config["meas_lo_freq"]
    ]

    # override defaults if single entry for ``schedule_los``
    schedule_los = qobj_config.pop("schedule_los", [])
    if len(schedule_los) == 1:
        lo_dict = schedule_los[0]
        q_los = lo_converter.get_qubit_los(lo_dict)
        # Hz -> GHz
        if q_los:
            qobj_config["qubit_lo_freq"] = [freq / 1e9 for freq in q_los]
        m_los = lo_converter.get_meas_los(lo_dict)
        if m_los:
            qobj_config["meas_lo_freq"] = [freq / 1e9 for freq in m_los]

    return qobj.PulseQobjConfig(**qobj_config)
def _assemble_config(lo_converter: converters.LoConfigConverter,
                     experiment_config: Dict[str, Any],
                     run_config: RunConfig) -> qobj.PulseQobjConfig:
    """Assembles the QobjConfiguration from experimental config and runtime config.

    Args:
        lo_converter: The configured frequency converter and validator.
        experiment_config: Schedules to assemble.
        run_config: Configuration of the runtime environment.

    Returns:
        The assembled PulseQobjConfig.
    """
    qobj_config = run_config.to_dict()
    qobj_config.update(experiment_config)

    # Run config not needed in qobj config
    qobj_config.pop('meas_map', None)
    qobj_config.pop('qubit_lo_range', None)
    qobj_config.pop('meas_lo_range', None)

    # convert enums to serialized values
    meas_return = qobj_config.get('meas_return', 'avg')
    if isinstance(meas_return, qobj_utils.MeasReturnType):
        qobj_config['meas_return'] = meas_return.value

    meas_level = qobj_config.get('meas_level', 2)
    if isinstance(meas_level, qobj_utils.MeasLevel):
        qobj_config['meas_level'] = meas_level.value

    # convert lo frequencies to Hz
    qobj_config['qubit_lo_freq'] = [
        freq / 1e9 for freq in qobj_config['qubit_lo_freq']
    ]
    qobj_config['meas_lo_freq'] = [
        freq / 1e9 for freq in qobj_config['meas_lo_freq']
    ]

    # frequency sweep config
    schedule_los = qobj_config.pop('schedule_los', [])
    if len(schedule_los) == 1:
        lo_dict = schedule_los[0]
        q_los = lo_converter.get_qubit_los(lo_dict)
        # Hz -> GHz
        if q_los:
            qobj_config['qubit_lo_freq'] = [freq / 1e9 for freq in q_los]
        m_los = lo_converter.get_meas_los(lo_dict)
        if m_los:
            qobj_config['meas_lo_freq'] = [freq / 1e9 for freq in m_los]

    return qobj.PulseQobjConfig(**qobj_config)
def assemble_schedules(schedules: List[Schedule], qobj_id: int,
                       qobj_header: QobjHeader,
                       run_config: RunConfig) -> PulseQobj:
    """Assembles a list of schedules into a qobj that can be run on the backend.

    Args:
        schedules: Schedules to assemble.
        qobj_id: Identifier for the generated qobj.
        qobj_header: Header to pass to the results.
        run_config: Configuration of the runtime environment.

    Returns:
        The Qobj to be run on the backends.

    Raises:
        QiskitError: when frequency settings are not supplied.
    """
    if not hasattr(run_config, 'qubit_lo_freq'):
        raise QiskitError('qubit_lo_freq must be supplied.')
    if not hasattr(run_config, 'meas_lo_freq'):
        raise QiskitError('meas_lo_freq must be supplied.')

    lo_converter = LoConfigConverter(PulseQobjExperimentConfig,
                                     **run_config.to_dict())
    experiments, experiment_config = _assemble_experiments(
        schedules, lo_converter, run_config)
    qobj_config = _assemble_config(lo_converter, experiment_config, run_config)

    return PulseQobj(experiments=experiments,
                     qobj_id=qobj_id,
                     header=qobj_header,
                     config=qobj_config)
Ejemplo n.º 4
0
    def test_meas_los(self):
        """Test measurement channel configuration."""
        user_lo_config = LoConfig({self.device.q[0].measure: 3.5})
        converter = LoConfigConverter(PulseQobjExperimentConfig, [1.2], [3.4])

        valid_qobj = PulseQobjExperimentConfig(meas_lo_freq=[3.5])

        self.assertEqual(converter(user_lo_config), valid_qobj)
Ejemplo n.º 5
0
    def test_qubit_los(self):
        """Test qubit channel configuration."""
        user_lo_config = LoConfig({self.device.q[0].drive: 1.3})
        converter = LoConfigConverter(PulseQobjExperimentConfig, [1.2], [3.4])

        valid_qobj = PulseQobjExperimentConfig(qubit_lo_freq=[1.3])

        self.assertEqual(converter(user_lo_config), valid_qobj)
Ejemplo n.º 6
0
    def test_meas_los(self):
        """Test measurement channel configuration."""
        user_lo_config = LoConfig({MeasureChannel(0): 3.5e9})
        converter = LoConfigConverter(PulseQobjExperimentConfig, [1.2e9],
                                      [3.4e9], [(0., 5e9)], [(0., 5e9)])

        valid_qobj = PulseQobjExperimentConfig(meas_lo_freq=[3.5])

        self.assertEqual(converter(user_lo_config), valid_qobj)
Ejemplo n.º 7
0
    def test_qubit_los(self):
        """Test qubit channel configuration."""
        user_lo_config = LoConfig({DriveChannel(0): 1.3e9})
        converter = LoConfigConverter(PulseQobjExperimentConfig, [1.2e9],
                                      [3.4e9], [(0., 5e9)], [(0., 5e9)])

        valid_qobj = PulseQobjExperimentConfig(qubit_lo_freq=[1.3])

        self.assertEqual(converter(user_lo_config), valid_qobj)
Ejemplo n.º 8
0
def assemble_schedules(schedules, qobj_id, qobj_header, run_config):
    """Assembles a list of schedules into a qobj which can be run on the backend.

    Args:
        schedules (list[Schedule]): schedules to assemble
        qobj_id (int): identifier for the generated qobj
        qobj_header (QobjHeader): header to pass to the results
        run_config (RunConfig): configuration of the runtime environment
    Returns:
        PulseQobj: the Qobj to be run on the backends
    Raises:
        QiskitError: when invalid schedules or configs are provided
    """
    if hasattr(run_config, 'instruction_converter'):
        instruction_converter = run_config.instruction_converter
    else:
        instruction_converter = InstructionToQobjConverter

    qobj_config = run_config.to_dict()

    qubit_lo_freq = qobj_config.get('qubit_lo_freq', None)
    if qubit_lo_freq is None:
        raise QiskitError('qubit_lo_freq must be supplied.')

    meas_lo_freq = qobj_config.get('meas_lo_freq', None)
    if meas_lo_freq is None:
        raise QiskitError('meas_lo_freq must be supplied.')

    qubit_lo_range = qobj_config.pop('qubit_lo_range', None)
    meas_lo_range = qobj_config.pop('meas_lo_range', None)
    meas_map = qobj_config.pop('meas_map', None)

    # convert enums to serialized values
    meas_return = qobj_config.get('meas_return', 'avg')
    if isinstance(meas_return, MeasReturnType):
        qobj_config['meas_return'] = meas_return.value

    meas_level = qobj_config.get('meas_return', 2)
    if isinstance(meas_level, MeasLevel):
        qobj_config['meas_level'] = meas_level.value

    instruction_converter = instruction_converter(PulseQobjInstruction, **qobj_config)

    lo_converter = LoConfigConverter(PulseQobjExperimentConfig,
                                     qubit_lo_range=qubit_lo_range,
                                     meas_lo_range=meas_lo_range,
                                     **qobj_config)

    memory_slot_size = 0

    # Pack everything into the Qobj
    qobj_schedules = []
    user_pulselib = {}
    for idx, schedule in enumerate(schedules):
        # instructions
        max_memory_slot = 0
        qobj_instructions = []

        # Instructions are returned as tuple of shifted time and instruction
        for shift, instruction in schedule.instructions:
            # TODO: support conditional gate

            if isinstance(instruction, DelayInstruction):
                # delay instructions are ignored as timing is explicit within qobj
                continue

            elif 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
            elif isinstance(instruction, AcquireInstruction):
                max_memory_slot = max(max_memory_slot,
                                      *[slot.index for slot in instruction.mem_slots])
                if meas_map:
                    # verify all acquires satisfy meas_map
                    _validate_meas_map(instruction, meas_map)

            converted_instruction = instruction_converter(shift, instruction)
            qobj_instructions.append(converted_instruction)

        # memory slot size is memory slot index + 1 because index starts from zero
        exp_memory_slot_size = max_memory_slot + 1
        memory_slot_size = max(memory_slot_size, exp_memory_slot_size)

        # experiment header
        # TODO: add other experimental header items (see circuit assembler)
        qobj_experiment_header = QobjExperimentHeader(
            memory_slots=exp_memory_slot_size,
            name=schedule.name or 'Experiment-%d' % idx
        )

        qobj_schedules.append({
            'header': qobj_experiment_header,
            'instructions': qobj_instructions
        })

    # set number of memoryslots
    qobj_config['memory_slots'] = memory_slot_size

    # setup pulse_library
    qobj_config['pulse_library'] = [PulseLibraryItem(name=pulse.name, samples=pulse.samples)
                                    for pulse in user_pulselib.values()]

    # create qobj experiment field
    experiments = []
    schedule_los = qobj_config.pop('schedule_los', [])

    if len(schedule_los) == 1:
        lo_dict = schedule_los[0]
        # update global config
        q_los = lo_converter.get_qubit_los(lo_dict)
        if q_los:
            qobj_config['qubit_lo_freq'] = q_los
        m_los = lo_converter.get_meas_los(lo_dict)
        if m_los:
            qobj_config['meas_lo_freq'] = m_los

    if schedule_los:
        # multiple frequency setups
        if len(qobj_schedules) == 1:
            # frequency sweep
            for lo_dict in schedule_los:
                experiments.append(PulseQobjExperiment(
                    instructions=qobj_schedules[0]['instructions'],
                    header=qobj_schedules[0]['header'],
                    config=lo_converter(lo_dict)
                ))
        elif len(qobj_schedules) == len(schedule_los):
            # n:n setup
            for lo_dict, schedule in zip(schedule_los, qobj_schedules):
                experiments.append(PulseQobjExperiment(
                    instructions=schedule['instructions'],
                    header=schedule['header'],
                    config=lo_converter(lo_dict)
                ))
        else:
            raise QiskitError('Invalid LO setting is specified. '
                              'The LO should be configured for each schedule, or '
                              'single setup for all schedules (unique), or '
                              'multiple setups for a single schedule (frequency sweep),'
                              'or no LO configured at all.')
    else:
        # unique frequency setup
        for schedule in qobj_schedules:
            experiments.append(PulseQobjExperiment(
                instructions=schedule['instructions'],
                header=schedule['header'],
            ))

    qobj_config = PulseQobjConfig(**qobj_config)

    return PulseQobj(qobj_id=qobj_id,
                     config=qobj_config,
                     experiments=experiments,
                     header=qobj_header)
Ejemplo n.º 9
0
def assemble_schedules(schedules,
                       qobj_id=None,
                       qobj_header=None,
                       run_config=None):
    """Assembles a list of schedules into a qobj which can be run on the backend.
    Args:
        schedules (list[Schedule]): schedules to assemble
        qobj_id (int): identifier for the generated qobj
        qobj_header (QobjHeader): header to pass to the results
        run_config (RunConfig): configuration of the runtime environment
    Returns:
        PulseQobj: the Qobj to be run on the backends
    Raises:
        QiskitError: when invalid schedules or configs are provided
    """
    qobj_config = QasmQobjConfig()
    if run_config:
        qobj_config = QasmQobjConfig(**run_config.to_dict())

    # Get appropriate convertors
    instruction_converter = PulseQobjConverter
    instruction_converter = instruction_converter(PulseQobjInstruction,
                                                  **run_config.to_dict())
    lo_converter = LoConfigConverter(PulseQobjExperimentConfig,
                                     run_config.qubit_lo_freq,
                                     run_config.meas_lo_freq,
                                     **run_config.to_dict())

    # Pack everything into the Qobj
    qobj_schedules = []
    user_pulselib = set()
    for idx, schedule in enumerate(schedules):
        # instructions
        qobj_instructions = []
        # Instructions are returned as tuple of shifted time and instruction
        for shift, instruction in list(schedule.flatten()):
            # TODO: support conditional gate
            qobj_instructions.append(instruction_converter(shift, instruction))
            if isinstance(instruction, PulseInstruction):
                # add samples to pulse library
                user_pulselib.add(instruction.command)
        # experiment header
        qobj_experiment_header = QobjExperimentHeader(
            name=schedule.name or 'Experiment-%d' % idx)

        qobj_schedules.append({
            'header': qobj_experiment_header,
            'instructions': qobj_instructions
        })

    # setup pulse_library
    run_config.pulse_library = [
        QobjPulseLibrary(name=pulse.name, samples=pulse.samples)
        for pulse in user_pulselib
    ]

    # create qob experiment field
    experiments = []
    if len(run_config.schedule_los) == 1:
        lo_dict = run_config.schedule_los.pop()
        # update global config
        q_los = lo_converter.get_qubit_los(lo_dict)
        if q_los:
            run_config.qubit_lo_freq = q_los
        m_los = lo_converter.get_meas_los(lo_dict)
        if m_los:
            run_config.meas_lo_freq = m_los

    if run_config.schedule_los:
        # multiple frequency setups
        if len(qobj_schedules) == 1:
            # frequency sweep
            for lo_dict in run_config.schedule_los:
                experiments.append(
                    PulseQobjExperiment(
                        instructions=qobj_schedules[0]['instructions'],
                        experimentheader=qobj_schedules[0]['header'],
                        experimentconfig=lo_converter(lo_dict)))
        elif len(qobj_schedules) == len(run_config.schedule_los):
            # n:n setup
            for lo_dict, schedule in zip(run_config.schedule_los,
                                         qobj_schedules):
                experiments.append(
                    PulseQobjExperiment(
                        instructions=schedule['instructions'],
                        experimentheader=schedule['header'],
                        experimentconfig=lo_converter(lo_dict)))
        else:
            raise QiskitError(
                'Invalid LO setting is specified. '
                'The LO should be configured for each schedule, or '
                'single setup for all schedules (unique), or '
                'multiple setups for a single schedule (frequency sweep),'
                'or no LO configured at all.')
    else:
        # unique frequency setup
        for schedule in qobj_schedules:
            experiments.append(
                PulseQobjExperiment(
                    instructions=schedule['instructions'],
                    experimentheader=schedule['header'],
                ))

    qobj_config = PulseQobjConfig(**run_config.to_dict())

    return PulseQobj(qobj_id=qobj_id,
                     config=qobj_config,
                     experiments=experiments,
                     header=qobj_header)
Ejemplo n.º 10
0
def assemble_schedules(schedules, qobj_id, qobj_header, run_config):
    """Assembles a list of schedules into a qobj which can be run on the backend.
    Args:
        schedules (list[Schedule]): schedules to assemble
        qobj_id (int): identifier for the generated qobj
        qobj_header (QobjHeader): header to pass to the results
        run_config (RunConfig): configuration of the runtime environment
    Returns:
        PulseQobj: the Qobj to be run on the backends
    Raises:
        QiskitError: when invalid schedules or configs are provided
    """
    if hasattr(run_config, 'instruction_converter'):
        instruction_converter = run_config.instruction_converter
    else:
        instruction_converter = InstructionToQobjConverter

    qobj_config = run_config.to_dict()
    qubit_lo_range = qobj_config.pop('qubit_lo_range')
    meas_lo_range = qobj_config.pop('meas_lo_range')
    meas_map = qobj_config.pop('meas_map', None)
    instruction_converter = instruction_converter(PulseQobjInstruction, **qobj_config)

    lo_converter = LoConfigConverter(PulseQobjExperimentConfig, qubit_lo_range=qubit_lo_range,
                                     meas_lo_range=meas_lo_range, **qobj_config)

    # Pack everything into the Qobj
    qobj_schedules = []
    user_pulselib = set()
    for idx, schedule in enumerate(schedules):
        # instructions
        qobj_instructions = []
        # Instructions are returned as tuple of shifted time and instruction
        for shift, instruction in schedule.instructions:
            # TODO: support conditional gate
            qobj_instructions.append(instruction_converter(shift, instruction))
            if isinstance(instruction, PulseInstruction):
                # add samples to pulse library
                user_pulselib.add(instruction.command)
            if isinstance(instruction, AcquireInstruction):
                if meas_map:
                    # verify all acquires satisfy meas_map
                    _validate_meas_map(instruction, meas_map)

        # experiment header
        qobj_experiment_header = QobjExperimentHeader(
            name=schedule.name or 'Experiment-%d' % idx
        )

        qobj_schedules.append({
            'header': qobj_experiment_header,
            'instructions': qobj_instructions
        })

    # setup pulse_library
    qobj_config['pulse_library'] = [PulseLibraryItem(name=pulse.name, samples=pulse.samples)
                                    for pulse in user_pulselib]

    # create qobj experiment field
    experiments = []
    schedule_los = qobj_config.pop('schedule_los', [])

    if len(schedule_los) == 1:
        lo_dict = schedule_los[0]
        # update global config
        q_los = lo_converter.get_qubit_los(lo_dict)
        if q_los:
            qobj_config['qubit_lo_freq'] = q_los
        m_los = lo_converter.get_meas_los(lo_dict)
        if m_los:
            qobj_config['meas_lo_freq'] = m_los

    if schedule_los:
        # multiple frequency setups
        if len(qobj_schedules) == 1:
            # frequency sweep
            for lo_dict in schedule_los:
                experiments.append(PulseQobjExperiment(
                    instructions=qobj_schedules[0]['instructions'],
                    header=qobj_schedules[0]['header'],
                    config=lo_converter(lo_dict)
                ))
        elif len(qobj_schedules) == len(schedule_los):
            # n:n setup
            for lo_dict, schedule in zip(schedule_los, qobj_schedules):
                experiments.append(PulseQobjExperiment(
                    instructions=schedule['instructions'],
                    header=schedule['header'],
                    config=lo_converter(lo_dict)
                ))
        else:
            raise QiskitError('Invalid LO setting is specified. '
                              'The LO should be configured for each schedule, or '
                              'single setup for all schedules (unique), or '
                              'multiple setups for a single schedule (frequency sweep),'
                              'or no LO configured at all.')
    else:
        # unique frequency setup
        for schedule in qobj_schedules:
            experiments.append(PulseQobjExperiment(
                instructions=schedule['instructions'],
                header=schedule['header'],
            ))

    qobj_config = PulseQobjConfig(**qobj_config)

    return PulseQobj(qobj_id=qobj_id,
                     config=qobj_config,
                     experiments=experiments,
                     header=qobj_header)