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 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 setUp(self): self.valid_qobj = PulseQobj( qobj_id='12345', header=QobjHeader(), config=PulseQobjConfig(shots=1024, memory_slots=2, max_credits=10, meas_level=1, memory_slot_size=8192, meas_return='avg', pulse_library=[ PulseLibraryItem(name='pulse0', samples=[ 0.0 + 0.0j, 0.5 + 0.0j, 0.0 + 0.0j ]) ], qubit_lo_freq=[4.9], meas_lo_freq=[6.9], rep_time=1000), experiments=[ PulseQobjExperiment(instructions=[ PulseQobjInstruction(name='pulse0', t0=0, ch='d0'), PulseQobjInstruction(name='fc', t0=5, ch='d0', phase=1.57), PulseQobjInstruction(name='fc', t0=5, ch='d0', phase=0.), PulseQobjInstruction(name='fc', t0=5, ch='d0', phase='P1'), PulseQobjInstruction( name='pv', t0=10, ch='d0', val=0.1 + 0.0j), PulseQobjInstruction(name='pv', t0=10, ch='d0', val='P1'), PulseQobjInstruction(name='acquire', t0=15, duration=5, qubits=[0], memory_slot=[0], kernels=[ QobjMeasurementOption( name='boxcar', params={ "start_window": 0, "stop_window": 5 }) ]) ]) ]) self.valid_dict = { 'qobj_id': '12345', 'type': 'PULSE', 'schema_version': '1.1.0', 'header': {}, 'config': { 'max_credits': 10, 'memory_slots': 2, 'shots': 1024, 'meas_level': 1, 'memory_slot_size': 8192, 'meas_return': 'avg', 'pulse_library': [{ 'name': 'pulse0', 'samples': [0, 0.5, 0] }], 'qubit_lo_freq': [4.9], 'meas_lo_freq': [6.9], 'rep_time': 1000 }, 'experiments': [{ 'instructions': [{ 'name': 'pulse0', 't0': 0, 'ch': 'd0' }, { 'name': 'fc', 't0': 5, 'ch': 'd0', 'phase': 1.57 }, { 'name': 'fc', 't0': 5, 'ch': 'd0', 'phase': 0 }, { 'name': 'fc', 't0': 5, 'ch': 'd0', 'phase': 'P1' }, { 'name': 'pv', 't0': 10, 'ch': 'd0', 'val': 0.1 + 0j }, { 'name': 'pv', 't0': 10, 'ch': 'd0', 'val': 'P1' }, { 'name': 'acquire', 't0': 15, 'duration': 5, 'qubits': [0], 'memory_slot': [0], 'kernels': [{ 'name': 'boxcar', 'params': { 'start_window': 0, 'stop_window': 5 } }] }] }] }
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)
def setUp(self): super().setUp() self.valid_qobj = PulseQobj( qobj_id="12345", header=QobjHeader(), config=PulseQobjConfig( shots=1024, memory_slots=2, max_credits=10, meas_level=1, memory_slot_size=8192, meas_return="avg", pulse_library=[ PulseLibraryItem( name="pulse0", samples=[0.0 + 0.0j, 0.5 + 0.0j, 0.0 + 0.0j]) ], qubit_lo_freq=[4.9], meas_lo_freq=[6.9], rep_time=1000, ), experiments=[ PulseQobjExperiment(instructions=[ PulseQobjInstruction(name="pulse0", t0=0, ch="d0"), PulseQobjInstruction(name="fc", t0=5, ch="d0", phase=1.57), PulseQobjInstruction(name="fc", t0=5, ch="d0", phase=0.0), PulseQobjInstruction(name="fc", t0=5, ch="d0", phase="P1"), PulseQobjInstruction( name="setp", t0=10, ch="d0", phase=3.14), PulseQobjInstruction( name="setf", t0=10, ch="d0", frequency=8.0), PulseQobjInstruction( name="shiftf", t0=10, ch="d0", frequency=4.0), PulseQobjInstruction( name="acquire", t0=15, duration=5, qubits=[0], memory_slot=[0], kernels=[ QobjMeasurementOption(name="boxcar", params={ "start_window": 0, "stop_window": 5 }) ], ), ]) ], ) self.valid_dict = { "qobj_id": "12345", "type": "PULSE", "schema_version": "1.2.0", "header": {}, "config": { "max_credits": 10, "memory_slots": 2, "shots": 1024, "meas_level": 1, "memory_slot_size": 8192, "meas_return": "avg", "pulse_library": [{ "name": "pulse0", "samples": [0, 0.5, 0] }], "qubit_lo_freq": [4.9], "meas_lo_freq": [6.9], "rep_time": 1000, }, "experiments": [{ "instructions": [ { "name": "pulse0", "t0": 0, "ch": "d0" }, { "name": "fc", "t0": 5, "ch": "d0", "phase": 1.57 }, { "name": "fc", "t0": 5, "ch": "d0", "phase": 0 }, { "name": "fc", "t0": 5, "ch": "d0", "phase": "P1" }, { "name": "setp", "t0": 10, "ch": "d0", "phase": 3.14 }, { "name": "setf", "t0": 10, "ch": "d0", "frequency": 8.0 }, { "name": "shiftf", "t0": 10, "ch": "d0", "frequency": 4.0 }, { "name": "acquire", "t0": 15, "duration": 5, "qubits": [0], "memory_slot": [0], "kernels": [{ "name": "boxcar", "params": { "start_window": 0, "stop_window": 5 } }], }, ] }], }