def update_backend_schema(self, input_parser): """ Updates backend schema """ if JSONSchema.BACKEND not in self._schema['properties']: return # Updates defaults provider/backend default_provider_name = None default_backend_name = None orig_backend_properties = self._original_schema.get( 'properties', {}).get(JSONSchema.BACKEND, {}).get('properties') if orig_backend_properties is not None: default_provider_name = orig_backend_properties.get( JSONSchema.PROVIDER, {}).get('default') default_backend_name = orig_backend_properties.get( JSONSchema.NAME, {}).get('default') providers = get_local_providers() if default_provider_name is None or default_provider_name not in providers: # use first provider available providers_items = providers.items() provider_tuple = next( iter(providers_items)) if len(providers_items) > 0 else ('', []) default_provider_name = provider_tuple[0] if default_backend_name is None or default_backend_name not in providers.get( default_provider_name, []): # use first backend available in provider default_backend_name = providers.get( default_provider_name)[0] if len( providers.get(default_provider_name, [])) > 0 else '' self._schema['properties'][JSONSchema.BACKEND] = { 'type': 'object', 'properties': { JSONSchema.PROVIDER: { 'type': 'string', 'default': default_provider_name }, JSONSchema.NAME: { 'type': 'string', 'default': default_backend_name }, }, 'required': [JSONSchema.PROVIDER, JSONSchema.NAME], 'additionalProperties': False, } provider_name = input_parser.get_section_property( JSONSchema.BACKEND, JSONSchema.PROVIDER, default_provider_name) backend_names = get_backends_from_provider(provider_name) backend_name = input_parser.get_section_property( JSONSchema.BACKEND, JSONSchema.NAME, default_backend_name) if backend_name not in backend_names: # use first backend available in provider backend_name = backend_names[0] if len(backend_names) > 0 else '' backend = get_backend_from_provider(provider_name, backend_name) config = backend.configuration() # Include shots in schema only if not a statevector backend. # For statevector, shots will be set to 1, in QiskitAqua if not is_statevector_backend(backend): self._schema['properties'][ JSONSchema.BACKEND]['properties']['shots'] = { 'type': 'integer', 'minimum': 1, } default_shots = 1024 # ensure default_shots <= max_shots if config.max_shots: default_shots = min(default_shots, config.max_shots) self._schema['properties'][JSONSchema.BACKEND]['properties'][ 'shots']['maximum'] = config.max_shots self._schema['properties'][JSONSchema.BACKEND]['properties'][ 'shots']['default'] = default_shots self._schema['properties'][ JSONSchema.BACKEND]['properties']['skip_transpiler'] = { 'type': 'boolean', 'default': False, } coupling_map_devices = [] noise_model_devices = [] check_coupling_map = is_simulator_backend(backend) check_noise_model = is_aer_provider( backend) and not is_aer_statevector_backend(backend) try: if (check_coupling_map or check_noise_model) and has_ibmq(): backend_names = get_backends_from_provider('qiskit.IBMQ') for backend_name in backend_names: ibmq_backend = get_backend_from_provider( 'qiskit.IBMQ', backend_name) if is_simulator_backend(ibmq_backend): continue if check_noise_model: noise_model_devices.append('qiskit.IBMQ:' + backend_name) if check_coupling_map and ibmq_backend.configuration( ).coupling_map: coupling_map_devices.append('qiskit.IBMQ:' + backend_name) except Exception as e: logger.debug("Failed to load IBMQ backends. Error {}".format( str(e))) # Includes 'coupling map' and 'coupling_map_from_device' in schema only if a simulator backend. # Actual devices have a coupling map based on the physical configuration of the device. # The user can configure the coupling map so its the same as the coupling map # of a given device in order to better simulate running on the device. # Property 'coupling_map_from_device' is a list of provider:name backends that are # real devices e.g qiskit.IBMQ:ibmqx5. # If property 'coupling_map', an array, is provided, it overrides coupling_map_from_device, # the latter defaults to 'None'. So in total no coupling map is a default, i.e. all to all coupling is possible. if is_simulator_backend(backend): self._schema['properties'][ JSONSchema.BACKEND]['properties']['coupling_map'] = { 'type': ['array', 'null'], 'default': None, } if len(coupling_map_devices) > 0: coupling_map_devices.append(None) self._schema['properties'][JSONSchema.BACKEND]['properties'][ 'coupling_map_from_device'] = { 'type': ['string', 'null'], 'default': None, 'oneOf': [{ 'enum': coupling_map_devices }], } # noise model that can be setup for Aer simulator so as to model noise of an actual device. if len(noise_model_devices) > 0: noise_model_devices.append(None) self._schema['properties'][ JSONSchema.BACKEND]['properties']['noise_model'] = { 'type': ['string', 'null'], 'default': None, 'oneOf': [{ 'enum': noise_model_devices }], } # If a noise model is supplied then the basis gates is set as per the noise model # unless basis gates is not None in which case it overrides noise model and a warning msg is logged. # as it is an advanced use case. self._schema['properties'][ JSONSchema.BACKEND]['properties']['basis_gates'] = { 'type': ['array', 'null'], 'default': None, } # TODO: Not sure if we want to continue with initial_layout in declarative form. # It requires knowledge of circuit registers etc. Perhaps its best to leave this detail to programming API. self._schema['properties'][ JSONSchema.BACKEND]['properties']['initial_layout'] = { 'type': ['object', 'null'], 'default': None, } # The same default and minimum as current RunConfig values self._schema['properties'][ JSONSchema.BACKEND]['properties']['max_credits'] = { 'type': 'integer', 'default': 10, 'minimum': 3, 'maximum': 10, } # Timeout and wait are for remote backends where we have to connect over network if not is_local_backend(backend): self._schema['properties'][ JSONSchema.BACKEND]['properties']['timeout'] = { "type": ["number", "null"], 'default': None, } self._schema['properties'][ JSONSchema.BACKEND]['properties']['wait'] = { 'type': 'number', 'default': 5.0, 'minimum': 0.0, }
def _set_section_property_without_checking_defaults( self, section_name, property_name, value): """ Args: section_name (str): the name of the section, case insensitive property_name (str): the name of the property value (obj): the value of the property Returns: Bool: True if value changed Raises: AquaError: validation error """ section_name = JSONSchema.format_section_name(section_name).lower() property_name = JSONSchema.format_property_name(property_name) value = self._json_schema.check_property_value(section_name, property_name, value) types = self.get_property_types(section_name, property_name) sections_temp = copy.deepcopy(self._sections) BaseParser._set_section_property(sections_temp, section_name, property_name, value, types) msg = self._json_schema.validate_property(sections_temp, section_name, property_name) if msg is not None: raise AquaError("{}.{}: Value '{}': '{}'".format( section_name, property_name, value, msg)) value_changed = False old_value = None if section_name not in self._sections: value_changed = True elif property_name not in self._sections[section_name]: value_changed = True else: old_value = self.get_section_property(section_name, property_name) value_changed = (old_value != value) if not value_changed: # nothing changed return False # check if the provider/backend is loadable and valid # set values from self.backend if exists if JSONSchema.BACKEND == section_name and \ property_name in [JSONSchema.PROVIDER, JSONSchema.NAME]: if self.backend is not None: value = self.backend.name() \ if property_name == JSONSchema.NAME else get_provider_from_backend(self.backend) elif property_name == JSONSchema.NAME: provider_name = self.get_section_property( section_name, JSONSchema.PROVIDER) backend_names = get_backends_from_provider(provider_name) if value not in backend_names: raise AquaError( "Backend '{}' not valid for provider: '{}' backends: '{}'" .format(value, provider_name, backend_names)) # update value internally BaseParser._set_section_property(self._sections, section_name, property_name, value, types) if JSONSchema.BACKEND == section_name and property_name == JSONSchema.PROVIDER: if self.backend is not None: # set value from self.backend if exists BaseParser._set_section_property(self._sections, section_name, JSONSchema.NAME, self.backend.name(), ['string']) else: backend_name = self.get_section_property( section_name, JSONSchema.NAME) backend_names = get_backends_from_provider(value) if backend_name not in backend_names: # use first backend available in provider backend_name = backend_names[0] if backend_names else '' BaseParser._set_section_property(self._sections, section_name, JSONSchema.NAME, backend_name, ['string']) # update backend schema if JSONSchema.BACKEND == section_name and \ property_name in [JSONSchema.PROVIDER, JSONSchema.NAME]: # update backend schema self._json_schema.update_backend_schema(self) return True if property_name == JSONSchema.NAME: if BaseParser.is_pluggable_section(section_name): self._json_schema.update_pluggable_schemas(self) self._update_dependency_sections(section_name) # remove any previous pluggable sections not in new dependency list old_dependencies = \ self._get_dependency_sections(section_name, old_value) \ if old_value is not None else set() new_dependencies = \ self._get_dependency_sections(section_name, value) \ if value is not None else set() for pluggable_name in old_dependencies.difference( new_dependencies): if pluggable_name in self._sections: del self._sections[pluggable_name] # reorder sections self._sections = self._order_sections(self._sections) return True if JSONSchema.PROBLEM == section_name: self._update_algorithm_problem() self.post_set_section_property(section_name, property_name) return True