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)
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)
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)
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)
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)
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)
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)
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)