Exemple #1
0
    def _config_the_best_mode(self, operator, backend):

        if not isinstance(operator, (WeightedPauliOperator, MatrixOperator,
                                     TPBGroupedWeightedPauliOperator)):
            logger.debug("Unrecognized operator type, skip auto conversion.")
            return operator

        ret_op = operator
        if not is_statevector_backend(backend) and not (
                is_aer_provider(backend)
                and self._quantum_instance.run_config.shots == 1):
            if isinstance(operator, (WeightedPauliOperator, MatrixOperator)):
                logger.debug(
                    "When running with Qasm simulator, grouped pauli can "
                    "save number of measurements. "
                    "We convert the operator into grouped ones.")
                ret_op = op_converter.to_tpb_grouped_weighted_pauli_operator(
                    operator, TPBGroupedWeightedPauliOperator.sorted_grouping)
        else:
            if not is_aer_provider(backend):
                if not isinstance(operator, MatrixOperator):
                    logger.info(
                        "When running with non-Aer statevector simulator, "
                        "represent operator as a matrix could "
                        "achieve the better performance. We convert "
                        "the operator to matrix.")
                    ret_op = op_converter.to_matrix_operator(operator)
            else:
                if not isinstance(operator, WeightedPauliOperator):
                    logger.info("When running with Aer simulator, "
                                "represent operator as weighted paulis could "
                                "achieve the better performance. We convert "
                                "the operator to weighted paulis.")
                    ret_op = op_converter.to_weighted_pauli_operator(operator)
        return ret_op
Exemple #2
0
    def construct_circuit(self, parameter, backend=None, use_simulator_operator_mode=False,
                          statevector_mode=None, circuit_name_prefix=''):
        """Generate the circuits.

        Args:
            parameter (numpy.ndarray): parameters for variational form.
            backend (qiskit.BaseBackend, optional): backend object.
            use_simulator_operator_mode (bool, optional): is backend from AerProvider, if True and mode is paulis,
                           single circuit is generated.
            statevector_mode (bool, optional): indicate which type of simulator are going to use.
            circuit_name_prefix (str, optional): a prefix of circuit name

        Returns:
            [QuantumCircuit]: the generated circuits with Hamiltonian.
        """

        if backend is not None:
            warnings.warn("backend option is deprecated and it will be removed after 0.6, "
                          "Use `statevector_mode` instead", DeprecationWarning)
            statevector_mode = is_statevector_backend(backend)
        else:
            if statevector_mode is None:
                raise AquaError("Either backend or statevector_mode need to be provided.")

        wave_function = self._var_form.construct_circuit(parameter)
        circuits = self._operator.construct_evaluation_circuit(
            use_simulator_operator_mode=use_simulator_operator_mode, wave_function=wave_function,
            statevector_mode=statevector_mode, circuit_name_prefix=circuit_name_prefix)
        return circuits
Exemple #3
0
    def _check_quantum_instance_and_modes_consistent(self) -> None:
        """ Checks whether the statevector and param_qobj settings are compatible with the
        backend

        Raises:
            ValueError: statevector or param_qobj are True when not supported by backend.
        """
        if self._statevector and not is_statevector_backend(self.quantum_instance.backend):
            raise ValueError('Statevector mode for circuit sampling requires statevector '
                             'backend, not {}.'.format(self.quantum_instance.backend))

        if self._param_qobj and not is_aer_provider(self.quantum_instance.backend):
            raise ValueError('Parameterized Qobj mode requires Aer '
                             'backend, not {}.'.format(self.quantum_instance.backend))
Exemple #4
0
    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 is_statevector(self):
     """Return True if backend is a statevector-type simulator."""
     return is_statevector_backend(self._backend)
Exemple #6
0
    def build(operator: OperatorBase,
              backend: Optional[Union[Backend, BaseBackend, QuantumInstance]] = None,
              include_custom: bool = True) -> ExpectationBase:
        """
        A factory method for convenient automatic selection of an Expectation based on the
        Operator to be converted and backend used to sample the expectation value.

        Args:
            operator: The Operator whose expectation value will be taken.
            backend: The backend which will be used to sample the expectation value.
            include_custom: Whether the factory will include the (Aer) specific custom
                expectations if their behavior against the backend might not be as expected.
                For instance when using Aer qasm_simulator with paulis the Aer snapshot can
                be used but the outcome lacks shot noise and hence does not intuitively behave
                overall as people might expect when choosing a qasm_simulator. It is however
                fast as long as the more state vector like behavior is acceptable.

        Returns:
            The expectation algorithm which best fits the Operator and backend.

        Raises:
            ValueError: If operator is not of a composition for which we know the best Expectation
                method.
        """
        backend_to_check = backend.backend if isinstance(backend, QuantumInstance) else backend

        # pylint: disable=cyclic-import,import-outside-toplevel
        primitives = operator.primitive_strings()
        if primitives == {'Pauli'}:

            if backend_to_check is None:
                # If user has Aer but didn't specify a backend, use the Aer fast expectation
                if has_aer():
                    from qiskit import Aer
                    backend_to_check = Aer.get_backend('qasm_simulator')
                # If user doesn't have Aer, use statevector_simulator
                # for < 16 qubits, and qasm with warning for more.
                else:
                    if operator.num_qubits <= 16:
                        backend_to_check = BasicAer.get_backend('statevector_simulator')
                    else:
                        logging.warning(
                            '%d qubits is a very large expectation value. '
                            'Consider installing Aer to use '
                            'Aer\'s fast expectation, which will perform better here. We\'ll use '
                            'the BasicAer qasm backend for this expectation to avoid having to '
                            'construct the %dx%d operator matrix.',
                            operator.num_qubits,
                            2 ** operator.num_qubits,
                            2 ** operator.num_qubits)
                        backend_to_check = BasicAer.get_backend('qasm_simulator')

            # If the user specified Aer qasm backend and is using a
            # Pauli operator, use the Aer fast expectation if we are including such
            # custom behaviors.
            if is_aer_qasm(backend_to_check) and include_custom:
                return AerPauliExpectation()

            # If the user specified a statevector backend (either Aer or BasicAer),
            # use a converter to produce a
            # Matrix operator and compute using matmul
            elif is_statevector_backend(backend_to_check):
                if operator.num_qubits >= 16:
                    logging.warning(
                        'Note: Using a statevector_simulator with %d qubits can be very expensive. '
                        'Consider using the Aer qasm_simulator instead to take advantage of Aer\'s '
                        'built-in fast Pauli Expectation', operator.num_qubits)
                return MatrixExpectation()

            # All other backends, including IBMQ, BasicAer QASM, go here.
            else:
                return PauliExpectation()

        elif primitives == {'Matrix'}:
            return MatrixExpectation()

        else:
            raise ValueError('Expectations of Mixed Operators not yet supported.')