def build_algorithm_from_dict(params, algo_input=None, backend=None): """ Construct algorithm as named in params, using params and algo_input as input data and returning a QuantumAlgorithm and QuantumInstance instance Args: params (dict): Dictionary of params for algo and dependent objects algo_input (AlgorithmInput): Main input data for algorithm. Optional, an algo may run entirely from params backend (BaseBackend): Backend object to be used in place of backend name Returns: Ready-to-run QuantumAlgorithm and QuantumInstance as specified in input parameters. Note that no QuantumInstance will be returned if none is specified - None will be returned instead. """ _discover_on_demand() inputparser = InputParser(params) inputparser.parse() # before merging defaults attempts to find a provider for the backend in case no # provider was passed if backend is None and inputparser.get_section_property( JSONSchema.BACKEND, JSONSchema.PROVIDER) is None: backend_name = inputparser.get_section_property( JSONSchema.BACKEND, JSONSchema.NAME) if backend_name is not None: inputparser.set_section_property( JSONSchema.BACKEND, JSONSchema.PROVIDER, get_provider_from_backend(backend_name)) inputparser.validate_merge_defaults() logger.debug('Algorithm Input: {}'.format( json.dumps(inputparser.get_sections(), sort_keys=True, indent=4))) algo_name = inputparser.get_section_property(PluggableType.ALGORITHM.value, JSONSchema.NAME) if algo_name is None: raise AquaError('Missing algorithm name') if algo_name not in local_pluggables(PluggableType.ALGORITHM): raise AquaError( 'Algorithm "{0}" missing in local algorithms'.format(algo_name)) if algo_input is None: input_name = inputparser.get_section_property('input', JSONSchema.NAME) if input_name is not None: input_params = copy.deepcopy( inputparser.get_section_properties('input')) del input_params[JSONSchema.NAME] convert_json_to_dict(input_params) algo_input = get_pluggable_class( PluggableType.INPUT, input_name).from_params(input_params) algo_params = copy.deepcopy(inputparser.get_sections()) algorithm = get_pluggable_class(PluggableType.ALGORITHM, algo_name).init_params( algo_params, algo_input) random_seed = inputparser.get_section_property(JSONSchema.PROBLEM, 'random_seed') algorithm.random_seed = random_seed quantum_instance = None # setup backend backend_provider = inputparser.get_section_property( JSONSchema.BACKEND, JSONSchema.PROVIDER) backend_name = inputparser.get_section_property(JSONSchema.BACKEND, JSONSchema.NAME) if backend_provider is not None and backend_name is not None: # quantum algorithm backend_cfg = { k: v for k, v in inputparser.get_section(JSONSchema.BACKEND).items() if k not in [JSONSchema.PROVIDER, JSONSchema.NAME] } # TODO, how to build the noise model from a dictionary? backend_cfg['seed_mapper'] = random_seed pass_manager = PassManager() if backend_cfg.pop( 'skip_transpiler', False) else None if pass_manager is not None: backend_cfg['pass_manager'] = pass_manager if backend is None or not isinstance(backend, BaseBackend): backend = get_backend_from_provider(backend_provider, backend_name) backend_cfg['backend'] = backend # overwrite the basis_gates and coupling_map basis_gates = backend_cfg.pop('basis_gates', None) coupling_map = backend_cfg.pop('coupling_map', None) if backend.configuration().simulator: if basis_gates is not None: backend.configuration().basis_gates = basis_gates if coupling_map is not None: backend.configuration().coupling_map = coupling_map else: logger.warning( "Change basis_gates and coupling_map on a real device is disallowed." ) shots = backend_cfg.pop('shots', 1024) seed = random_seed max_credits = backend_cfg.pop('max_credits', 10) memory = backend_cfg.pop('memory', False) run_config = RunConfig(shots=shots, max_credits=max_credits, memory=memory) if seed is not None: run_config.seed = seed backend_cfg['run_config'] = run_config backend_cfg['skip_qobj_validation'] = inputparser.get_section_property( JSONSchema.PROBLEM, 'skip_qobj_validation') use_caching = inputparser.get_section_property(JSONSchema.PROBLEM, 'circuit_caching') if use_caching: deepcopy_qobj = inputparser.get_section_property( JSONSchema.PROBLEM, 'skip_qobj_deepcopy') cache_file = inputparser.get_section_property( JSONSchema.PROBLEM, 'circuit_cache_file') backend_cfg['circuit_cache'] = CircuitCache( skip_qobj_deepcopy=deepcopy_qobj, cache_file=cache_file) quantum_instance = QuantumInstance(**backend_cfg) # Note that quantum_instance can be None if none is specified return algorithm, quantum_instance
class QiskitAqua(object): """Main Aqua class.""" def __init__(self, params, algo_input=None, quantum_instance=None): """ Create an QiskitAqua object Args: params (dict): Dictionary of params for algo and dependent objects algo_input (AlgorithmInput): Main input data for algorithm. Optional, an algo may run entirely from params quantum_instance (QuantumInstance or BaseBackend): the experiemental settings to be used in place of backend name """ self._params = params self._algorithm_input = algo_input self._quantum_instance = None self._quantum_algorithm = None self._result = {} self._parser = None self._build_algorithm_from_dict(quantum_instance) @property def params(self): """Return Aqua params.""" return self._params @property def algorithm_input(self): """Return Algorithm Input.""" return self._algorithm_input @property def quantum_instance(self): """Return Quantum Instance.""" return self._quantum_instance @property def quantum_algorithm(self): """Return Qusntum Algorithm.""" return self._quantum_algorithm @property def result(self): """Return Experiment Result.""" return self._result @property def json_result(self): """Return Experiment Result as JSON.""" return convert_dict_to_json(self.result) if isinstance( self.result, dict) else None @property def parser(self): """Return Aqua parser.""" return self._parser def _build_algorithm_from_dict(self, quantum_instance): _discover_on_demand() self._parser = InputParser(self._params) self._parser.parse() # before merging defaults attempts to find a provider for the backend in case no # provider was passed if quantum_instance is None and self._parser.get_section_property( JSONSchema.BACKEND, JSONSchema.PROVIDER) is None: backend_name = self._parser.get_section_property( JSONSchema.BACKEND, JSONSchema.NAME) if backend_name is not None: self._parser.set_section_property( JSONSchema.BACKEND, JSONSchema.PROVIDER, get_provider_from_backend(backend_name)) self._parser.validate_merge_defaults() logger.debug('Algorithm Input: {}'.format( json.dumps(self._parser.get_sections(), sort_keys=True, indent=4))) algo_name = self._parser.get_section_property( PluggableType.ALGORITHM.value, JSONSchema.NAME) if algo_name is None: raise AquaError('Missing algorithm name') if algo_name not in local_pluggables(PluggableType.ALGORITHM): raise AquaError( 'Algorithm "{0}" missing in local algorithms'.format( algo_name)) if self._algorithm_input is None: input_name = self._parser.get_section_property( 'input', JSONSchema.NAME) if input_name is not None: input_params = copy.deepcopy( self._parser.get_section_properties('input')) del input_params[JSONSchema.NAME] convert_json_to_dict(input_params) self._algorithm_input = get_pluggable_class( PluggableType.INPUT, input_name).from_params(input_params) algo_params = copy.deepcopy(self._parser.get_sections()) self._quantum_algorithm = get_pluggable_class( PluggableType.ALGORITHM, algo_name).init_params(algo_params, self._algorithm_input) random_seed = self._parser.get_section_property( JSONSchema.PROBLEM, 'random_seed') self._quantum_algorithm.random_seed = random_seed if isinstance(quantum_instance, QuantumInstance): self._quantum_instance = quantum_instance return backend = None if isinstance(quantum_instance, BaseBackend): backend = quantum_instance elif quantum_instance is not None: raise AquaError( 'Invalid QuantumInstance or BaseBackend parameter {}.'.format( quantum_instance)) # setup backend backend_provider = self._parser.get_section_property( JSONSchema.BACKEND, JSONSchema.PROVIDER) backend_name = self._parser.get_section_property( JSONSchema.BACKEND, JSONSchema.NAME) if backend_provider is not None and backend_name is not None: # quantum algorithm backend_cfg = { k: v for k, v in self._parser.get_section( JSONSchema.BACKEND).items() if k not in [JSONSchema.PROVIDER, JSONSchema.NAME] } # TODO, how to build the noise model from a dictionary? backend_cfg['seed_mapper'] = random_seed pass_manager = PassManager() if backend_cfg.pop( 'skip_transpiler', False) else None if pass_manager is not None: backend_cfg['pass_manager'] = pass_manager if backend is None: backend = get_backend_from_provider(backend_provider, backend_name) backend_cfg['backend'] = backend # overwrite the basis_gates and coupling_map basis_gates = backend_cfg.pop('basis_gates', None) if isinstance(basis_gates, str): basis_gates = basis_gates.split(',') coupling_map = backend_cfg.pop('coupling_map', None) if backend.configuration().simulator: if basis_gates is not None: backend.configuration().basis_gates = basis_gates if coupling_map is not None: backend.configuration().coupling_map = coupling_map else: logger.warning( "Change basis_gates and coupling_map on a real device is disallowed." ) shots = backend_cfg.pop('shots', 1024) seed = random_seed max_credits = backend_cfg.pop('max_credits', 10) memory = backend_cfg.pop('memory', False) run_config = RunConfig(shots=shots, max_credits=max_credits, memory=memory) if seed is not None: run_config.seed = seed backend_cfg['run_config'] = run_config backend_cfg[ 'skip_qobj_validation'] = self._parser.get_section_property( JSONSchema.PROBLEM, 'skip_qobj_validation') use_caching = self._parser.get_section_property( JSONSchema.PROBLEM, 'circuit_caching') if use_caching: deepcopy_qobj = self._parser.get_section_property( JSONSchema.PROBLEM, 'skip_qobj_deepcopy') cache_file = self._parser.get_section_property( JSONSchema.PROBLEM, 'circuit_cache_file') backend_cfg['circuit_cache'] = CircuitCache( skip_qobj_deepcopy=deepcopy_qobj, cache_file=cache_file) self._quantum_instance = QuantumInstance(**backend_cfg) def run(self, json_output=False): if self.quantum_algorithm is None: raise AquaError('Missing Quantum Algorithm.') self._result = self.quantum_algorithm.run(self.quantum_instance) return self.json_result if json_output else self.result @staticmethod def run_algorithm_to_json(params, algo_input=None, jsonfile='algorithm.json'): """ Run algorithm as named in params. Using params and algo_input as input data and save the combined input as a json file. This json is self-contained and can later be used as a basis to call run_algorithm Args: params (dict): Dictionary of params for algo and dependent objects algo_input (AlgorithmInput): Main input data for algorithm. Optional, an algo may run entirely from params jsonfile (str): Name of file in which json should be saved Returns: Result dictionary containing the jsonfile name """ _discover_on_demand() inputparser = InputParser(params) inputparser.parse() inputparser.validate_merge_defaults() algo_params = copy.deepcopy(inputparser.get_sections()) if algo_input is not None: input_params = algo_input.to_params() convert_dict_to_json(input_params) algo_params['input'] = input_params algo_params['input']['name'] = algo_input.configuration['name'] logger.debug('Result: {}'.format( json.dumps(algo_params, sort_keys=True, indent=4))) with open(jsonfile, 'w') as fp: json.dump(algo_params, fp, sort_keys=True, indent=4) logger.info("Algorithm input file saved: '{}'".format(jsonfile)) return {'jsonfile': jsonfile}