Source code for qlauncher.routines.qiskit.backends.aqt_backend

 1""" AQT backend class for Qiskit routines """
 2from typing import Literal
 3from overrides import override
 4
 5from qiskit.providers import BackendV1, BackendV2
 6from qiskit.primitives import Sampler
 7from qiskit_ibm_runtime import Options
 8
 9from qlauncher.routines.qiskit import QiskitBackend
10from qlauncher.exceptions import DependencyError
11
12try:
13    from qiskit_aqt_provider import AQTProvider
14    from qiskit_aqt_provider.primitives import AQTSampler, AQTEstimator
15except ImportError as e:
16    raise DependencyError(e, install_hint='aqt') from e
17
18
[docs] 19class AQTBackend(QiskitBackend): 20 """ 21 An extension of QiskitBackend providing support for Alpine Quantum Technologies (AQT) devices. 22 23 Attributes: 24 token (str, optional): AQT token, used for authorization when using real device backends. 25 dotenv_path (str,optional): (recommended) Path to a .env file containing the AQT token. If dotenv_path is not None, the token will be ignored and the token from the .env file will be used. 26 27 Usage Example 28 ------------- 29 :: 30 31 backend = AQTBackend(token='valid_token', name='device') 32 33 or 34 35 :: 36 37 backend = AQTBackend(dotenv_path='./.env', name='device') 38 39 with a .env file: 40 41 :: 42 43 AQT_TOKEN=valid_token 44 45 """ 46 sampler: AQTSampler 47 estimator: AQTEstimator 48 49 def __init__( 50 self, 51 name: Literal['local_simulator', 'backendv1v2', 'device'], 52 options: Options | None = None, 53 backendv1v2: BackendV1 | BackendV2 | None = None, 54 auto_transpile_level: Literal[0, 1, 2, 3] | None = None, 55 token: str | None = None, 56 dotenv_path: str | None = None, 57 ) -> None: 58 59 # TODO: This will probably need to be updated to handle custom backend urls, when we get our own computer 60 if dotenv_path is None: 61 self.provider = AQTProvider(token if token is not None else "DEFAULT_TOKEN", load_dotenv=False) 62 else: 63 self.provider = AQTProvider(load_dotenv=True, dotenv_path=dotenv_path) 64 super().__init__(name, options=options, backendv1v2=backendv1v2, auto_transpile_level=auto_transpile_level) 65 66 @override 67 def _set_primitives_on_backend_name(self) -> None: 68 if self.name == 'local_simulator': 69 self.name = self.provider.backends(backend_type='offline_simulator', name=r".*no_noise")[0].name 70 elif self.name == 'backendv1v2': 71 if self.backendv1v2 is None: 72 raise ValueError("Please indicate a backend when in backendv1v2 mode.") 73 elif self.name == 'device': 74 available_online_backends = self.provider.backends(backend_type='device') 75 if len(available_online_backends) == 0: 76 raise ValueError(f"No online backends available for token {self.provider.access_token[:5]}...") 77 self.name = available_online_backends[0].name 78 else: 79 raise ValueError( 80 " ".join([ 81 f"Unsupported mode for this backend:'{self.name}'." 82 "Please use one of the following: ['local_simulator', 'backendv1v2', 'device']" 83 ]) 84 ) 85 86 if self.backendv1v2 is None: 87 self.backendv1v2 = self.provider.get_backend(name=self.name) 88 89 self.estimator = AQTEstimator(self.backendv1v2) 90 self.sampler = AQTSampler(self.backendv1v2) 91 92 self._configure_auto_behavior() 93 94 @property 95 def samplerV1(self) -> Sampler: 96 return self.sampler