def set_config(self, **kwargs):
        """Set configurations for the quantum instance."""
        for k, v in kwargs.items():
            if k in QuantumInstance._RUN_CONFIG:
                setattr(self._run_config, k, v)
            elif k in QuantumInstance._QJOB_CONFIG:
                self._qjob_config[k] = v
            elif k in QuantumInstance._COMPILE_CONFIG:
                self._compile_config[k] = v
            elif k in QuantumInstance._BACKEND_CONFIG:
                self._backend_config[k] = v
            elif k in QuantumInstance._BACKEND_OPTIONS:
                if not support_backend_options(self._backend):
                    raise QiskitError(
                        "backend_options can not be used with this backend "
                        "{} ({}).".format(self.backend_name,
                                          _get_backend_provider(
                                              self._backend)))

                if k in QuantumInstance._BACKEND_OPTIONS_QASM_ONLY and self.is_statevector:
                    raise QiskitError(
                        "'{}' is only applicable for qasm simulator but "
                        "statevector simulator is used as the backend.")

                if "backend_options" not in self._backend_options:
                    self._backend_options["backend_options"] = {}
                self._backend_options["backend_options"][k] = v
            elif k in QuantumInstance._NOISE_CONFIG:
                if not is_simulator_backend(
                        self._backend) or is_basicaer_provider(self._backend):
                    raise QiskitError(
                        "The noise model is not supported on the selected backend {} ({}) "
                        "only certain backends, such as Aer qasm support "
                        "noise.".format(self.backend_name,
                                        _get_backend_provider(self._backend)))

                self._noise_config[k] = v

            else:
                raise ValueError(f"unknown setting for the key ({k}).")
Esempio n. 2
0
    def __init__(
        self,
        backend,
        # run config
        shots: Optional[int] = None,
        seed_simulator: Optional[int] = None,
        max_credits: int = 10,
        # backend properties
        basis_gates: Optional[List[str]] = None,
        coupling_map=None,
        # transpile
        initial_layout=None,
        pass_manager=None,
        bound_pass_manager=None,
        seed_transpiler: Optional[int] = None,
        optimization_level: Optional[int] = None,
        # simulation
        backend_options: Optional[Dict] = None,
        noise_model=None,
        # job
        timeout: Optional[float] = None,
        wait: float = 5.0,
        # others
        skip_qobj_validation: bool = True,
        measurement_error_mitigation_cls: Optional[Callable] = None,
        cals_matrix_refresh_period: int = 30,
        measurement_error_mitigation_shots: Optional[int] = None,
        job_callback: Optional[Callable] = None,
        mit_pattern: Optional[List[List[int]]] = None,
        max_job_retries: int = 50,
    ) -> None:
        """
        Quantum Instance holds a Qiskit Terra backend as well as configuration for circuit
        transpilation and execution. When provided to an Aqua algorithm the algorithm will
        execute the circuits it needs to run using the instance.

        Args:
            backend (Union['Backend', 'BaseBackend']): Instance of selected backend
            shots: Number of repetitions of each circuit, for sampling. If None, the shots are
                extracted from the backend. If the backend has none set, the default is 1024.
            seed_simulator: Random seed for simulators
            max_credits: Maximum credits to use
            basis_gates: List of basis gate names supported by the
                target. Defaults to basis gates of the backend.
            coupling_map (Optional[Union['CouplingMap', List[List]]]):
                Coupling map (perhaps custom) to target in mapping
            initial_layout (Optional[Union['Layout', Dict, List]]):
                Initial layout of qubits in mapping
            pass_manager (Optional['PassManager']): Pass manager to handle how to compile the circuits.
                To run only this pass manager and not the ``bound_pass_manager``, call the
                :meth:`~qiskit.utils.QuantumInstance.transpile` method with the argument
                ``pass_manager=quantum_instance.unbound_pass_manager``.
            bound_pass_manager (Optional['PassManager']): A second pass manager to apply on bound
                circuits only, that is, circuits without any free parameters. To only run this pass
                manager and not ``pass_manager`` call the
                :meth:`~qiskit.utils.QuantumInstance.transpile` method with the argument
                ``pass_manager=quantum_instance.bound_pass_manager``.
                manager should also be run.
            seed_transpiler: The random seed for circuit mapper
            optimization_level: How much optimization to perform on the circuits.
                Higher levels generate more optimized circuits, at the expense of longer
                transpilation time.
            backend_options: All running options for backend, please refer
                to the provider of the backend for information as to what options it supports.
            noise_model (Optional['NoiseModel']): noise model for simulator
            timeout: Seconds to wait for job. If None, wait indefinitely.
            wait: Seconds between queries for job result
            skip_qobj_validation: Bypass Qobj validation to decrease circuit
                processing time during submission to backend.
            measurement_error_mitigation_cls: The approach to mitigate
                measurement errors. The classes :class:`~qiskit.utils.mitigation.CompleteMeasFitter`
                or :class:`~qiskit.utils.mitigation.TensoredMeasFitter` from the
                :mod:`qiskit.utils.mitigation` module can be used here as exact values, not
                instances. ``TensoredMeasFitter`` doesn't support the ``subset_fitter`` method.
            cals_matrix_refresh_period: How often to refresh the calibration
                matrix in measurement mitigation. in minutes
            measurement_error_mitigation_shots: The number of shots number for
                building calibration matrix. If None, the main `shots` parameter value is used.
            job_callback: Optional user supplied callback which can be used
                to monitor job progress as jobs are submitted for processing by an Aqua algorithm.
                The callback is provided the following arguments: `job_id, job_status,
                queue_position, job`
            mit_pattern: Qubits on which to perform the TensoredMeasFitter
                measurement correction, divided to groups according to tensors.
                If `None` and `qr` is given then assumed to be performed over the entire
                `qr` as one group (default `None`).
            max_job_retries(int): positive non-zero number of trials for the job set (-1 for
                infinite trials) (default: 50)

        Raises:
            QiskitError: the shots exceeds the maximum number of shots
            QiskitError: set noise model but the backend does not support that
            QiskitError: set backend_options but the backend does not support that
        """
        self._backend = backend
        self._backend_interface_version = _get_backend_interface_version(self._backend)
        self._pass_manager = pass_manager
        self._bound_pass_manager = bound_pass_manager

        # if the shots are none, try to get them from the backend
        if shots is None:
            from qiskit.providers.basebackend import BaseBackend  # pylint: disable=cyclic-import
            from qiskit.providers.backend import Backend  # pylint: disable=cyclic-import

            if isinstance(backend, (BaseBackend, Backend)):
                if hasattr(backend, "options"):  # should always be true for V1
                    backend_shots = backend.options.get("shots", 1024)
                    if shots != backend_shots:
                        logger.info(
                            "Overwriting the number of shots in the quantum instance with "
                            "the settings from the backend."
                        )
                    shots = backend_shots

        # safeguard if shots are still not set
        if shots is None:
            shots = 1024

        # pylint: disable=cyclic-import
        from qiskit.assembler.run_config import RunConfig

        run_config = RunConfig(shots=shots, max_credits=max_credits)
        if seed_simulator is not None:
            run_config.seed_simulator = seed_simulator

        self._run_config = run_config

        # setup backend config
        if self._backend_interface_version <= 1:
            basis_gates = basis_gates or backend.configuration().basis_gates
            coupling_map = coupling_map or getattr(backend.configuration(), "coupling_map", None)
            self._backend_config = {"basis_gates": basis_gates, "coupling_map": coupling_map}
        else:
            self._backend_config = {}

        # setup compile config
        self._compile_config = {
            "initial_layout": initial_layout,
            "seed_transpiler": seed_transpiler,
            "optimization_level": optimization_level,
        }

        # setup job config
        self._qjob_config = (
            {"timeout": timeout} if self.is_local else {"timeout": timeout, "wait": wait}
        )

        # setup noise config
        self._noise_config = {}
        if noise_model is not None:
            if is_simulator_backend(self._backend) and not is_basicaer_provider(self._backend):
                self._noise_config = {"noise_model": noise_model}
            else:
                raise QiskitError(
                    "The noise model is not supported "
                    "on the selected backend {} ({}) "
                    "only certain backends, such as Aer qasm simulator "
                    "support noise.".format(self.backend_name, _get_backend_provider(self._backend))
                )

        # setup backend options for run
        self._backend_options = {}
        if backend_options is not None:
            if support_backend_options(self._backend):
                self._backend_options = {"backend_options": backend_options}
            else:
                raise QiskitError(
                    "backend_options can not used with the backends in IBMQ provider."
                )

        # setup measurement error mitigation
        self._meas_error_mitigation_cls = None
        if self.is_statevector:
            if measurement_error_mitigation_cls is not None:
                raise QiskitError(
                    "Measurement error mitigation does not work with the statevector simulation."
                )
        else:
            self._meas_error_mitigation_cls = measurement_error_mitigation_cls
        self._meas_error_mitigation_fitters: Dict[str, Tuple[np.ndarray, float]] = {}
        # TODO: support different fitting method in error mitigation?
        self._meas_error_mitigation_method = "least_squares"
        self._cals_matrix_refresh_period = cals_matrix_refresh_period
        self._meas_error_mitigation_shots = measurement_error_mitigation_shots
        self._mit_pattern = mit_pattern

        if self._meas_error_mitigation_cls is not None:
            logger.info(
                "The measurement error mitigation is enabled. "
                "It will automatically submit an additional job to help "
                "calibrate the result of other jobs. "
                "The current approach will submit a job with 2^N circuits "
                "to build the calibration matrix, "
                "where N is the number of measured qubits. "
                "Furthermore, Aqua will re-use the calibration matrix for %s minutes "
                "and re-build it after that.",
                self._cals_matrix_refresh_period,
            )

        # setup others
        if is_ibmq_provider(self._backend):
            if skip_qobj_validation:
                logger.info(
                    "skip_qobj_validation was set True but this setting is not "
                    "supported by IBMQ provider and has been ignored."
                )
                skip_qobj_validation = False
        self._skip_qobj_validation = skip_qobj_validation
        self._circuit_summary = False
        self._job_callback = job_callback
        self._time_taken = 0.0
        self._max_job_retries = max_job_retries
        logger.info(self)