def _assemble_experiments( schedules: List[Union[pulse.ScheduleComponent, Tuple[int, pulse.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()) schedules = [ sched if isinstance(sched, pulse.Schedule) else pulse.Schedule(sched) for sched in schedules ] compressed_schedules = transforms.compress_pulses(schedules) user_pulselib = {} experiments = [] for idx, schedule in enumerate(compressed_schedules): qobj_instructions, max_memory_slot = _assemble_instructions( schedule, instruction_converter, run_config, user_pulselib) # 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=schedule.name or 'Experiment-%d' % idx) 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
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 'schedule_los' setting specified. If specified, it should be " "either have a single entry to apply the same LOs for each schedule or " "have length equal to the number of schedules.") instruction_converter = getattr(run_config, "instruction_converter", converters.InstructionToQobjConverter) instruction_converter = instruction_converter(qobj.PulseQobjInstruction, **run_config.to_dict()) formatted_schedules = [ transforms.target_qobj_transform(sched) for sched in schedules ] 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