Source code for mpqp.execution.simulated_devices

"""To execute a circuit on a noisy simulator that reproduces the noise model of a machine,
one can use a :class:`SimulatedDevice`. Inheriting from :class:`~mpqp.execution.devices.AvailableDevice`, it is the
mother class of all noisy devices reproducing real hardware for several providers.

For the moment, only IBM simulated devices are available (so called `FakeBackend`), but the structure is ready to allow
other simulated devices (QLM has this feature for instance."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Iterator, Optional

from mpqp.environment.var_cache import (
    _INSTALLED_MPQP_PROVIDERS,  # pyright: ignore[reportPrivateUsage]
)
from mpqp.environment.var_cache import InstalledProviders
from mpqp.execution import AvailableDevice

if TYPE_CHECKING:
    from qiskit_aer.backends.aer_simulator import AerSimulator
    from qiskit_aer.noise import NoiseModel as Qiskit_NoiseModel
    from qiskit_ibm_runtime.fake_provider.fake_backend import FakeBackendV2


[docs] class SimulatedDevice(AvailableDevice): """A class used to define simulators reproducing the noise of a real device. It implements the abstract methods of ``AvailableDevice``, and is used as a blueprint for all possible simulated devices (IBM, QLM, ...)."""
[docs] def is_gate_based(self) -> bool: return True
[docs] def is_simulator(self) -> bool: return True
[docs] def is_noisy_simulator(self) -> bool: return True
[docs] def is_remote(self) -> bool: return False
[docs] class StaticIBMSimulatedDevice(SimulatedDevice): """A class regrouping methods specific to an ``IBMSimulatedDevice``."""
[docs] def supports_observable(self) -> bool: return True
[docs] def supports_observable_ideal(self) -> bool: return True
[docs] def supports_samples(self) -> bool: return False
[docs] def supports_state_vector(self): return False
[docs] def to_noisy_simulator(self) -> "AerSimulator": """Instantiates and returns an ``AerSimulator`` (from qiskit_aer) with the noise model corresponding to this IBM fake device.""" from qiskit_aer.backends.aer_simulator import AerSimulator return AerSimulator.from_backend(self.value())
[docs] def to_noise_model(self) -> "Qiskit_NoiseModel": """Generates the qiskit ``NoiseModel`` corresponding to this IBM fake device.""" from qiskit_aer.noise import NoiseModel as Qiskit_NoiseModel return Qiskit_NoiseModel.from_backend(self.value())
[docs] @staticmethod def get_ibm_fake_providers() -> list[tuple[str, type["FakeBackendV2"]]]: if InstalledProviders.QISKIT_IBM_RUNTIME in _INSTALLED_MPQP_PROVIDERS: from qiskit_ibm_runtime import fake_provider from qiskit_ibm_runtime.fake_provider.fake_backend import FakeBackendV2 fake_imports = fake_provider.__dict__ return [ (name, device) for name, device in fake_imports.items() if name.startswith("Fake") and not name.startswith(("FakeProvider", "FakeFractional")) and issubclass(device, FakeBackendV2) and "cairo" not in name.lower() ] else: return []
class _LazyIBMSimulatedDevice: _instance: Optional[type[StaticIBMSimulatedDevice]] = None @classmethod def _init(cls) -> None: if cls._instance is None: providers = StaticIBMSimulatedDevice.get_ibm_fake_providers() cls._instance = StaticIBMSimulatedDevice("IBMSimulatedDevice", providers) for name, _ in providers: setattr(cls, name, cls._instance[name]) def __getattr__(self, name: str) -> Any: self._init() return getattr(self._instance, name) def __iter__(self) -> Iterator[Any]: self._init() assert self._instance is not None, "Instance not initialized" return iter(self._instance) def __getitem__(self, key: Any) -> Any: self._init() assert self._instance is not None, "Instance not initialized" return self._instance[key] def __call__(self, *args: Any, **kwargs: Any) -> Any: self._init() assert self._instance is not None, "Instance not initialized" return self._instance(*args, **kwargs) IBMSimulatedDevice = _LazyIBMSimulatedDevice() """Enum regrouping all so called IBM "fake devices" used to simulate noise of real hardware. The members of this Enum are generated dynamically from ``qiskit_ibm_runtime.fake_provider``."""