Source code for qbraid.runtime.qiskit.provider

# Copyright (C) 2024 qBraid
#
# This file is part of the qBraid-SDK
#
# The qBraid-SDK is free software released under the GNU General Public License v3
# or later. You can redistribute and/or modify it under the terms of the GPL v3.
# See the LICENSE file in the project root or <https://www.gnu.org/licenses/gpl-3.0.html>.
#
# THERE IS NO WARRANTY for the qBraid-SDK, as per Section 15 of the GPL v3.

"""
Module for configuring IBM provider credentials and authentication.

"""

import os
from typing import TYPE_CHECKING, Optional

import qiskit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime.accounts import ChannelType

from qbraid.programs import ProgramSpec
from qbraid.runtime.enums import DeviceType
from qbraid.runtime.profile import TargetProfile
from qbraid.runtime.provider import QuantumProvider

from .device import QiskitBackend

if TYPE_CHECKING:
    import qiskit_ibm_runtime

    import qbraid.runtime.qiskit


[docs] class QiskitRuntimeProvider(QuantumProvider): """ This class is responsible for managing the interactions and authentications with the IBM Quantum services. Attributes: token (str): IBM Cloud API key or IBM Quantum API token. runtime_service (qiskit_ibm_runtime.QiskitRuntimeService): IBM Quantum runtime service. """
[docs] def __init__( self, token: Optional[str] = None, channel: Optional[ChannelType] = None, **kwargs ): """ Initializes the QbraidProvider object with optional AWS and IBM Quantum credentials. Args: token (str, optional): IBM Quantum token. Defaults to None. """ self.token = token or os.getenv("QISKIT_IBM_TOKEN") self.channel = channel or os.getenv("QISKIT_IBM_CHANNEL", "ibm_quantum") self._runtime_service = QiskitRuntimeService( token=self.token, channel=self.channel, **kwargs )
@property def runtime_service(self) -> "qiskit_ibm_runtime.QiskitRuntimeService": """Returns the IBM Quantum runtime service.""" return self._runtime_service def save_config( self, token: Optional[str] = None, channel: Optional[str] = None, overwrite: bool = True, **kwargs, ) -> None: """Saves IBM runtime service account to disk for future use.""" token = token or self.token channel = channel or self.channel QiskitRuntimeService.save_account( token=token, channel=channel, overwrite=overwrite, **kwargs ) def _build_runtime_profile( self, backend: "qiskit_ibm_runtime.IBMBackend", program_spec: Optional[ProgramSpec] = None ) -> TargetProfile: """Builds a runtime profile from a backend.""" program_spec = program_spec or ProgramSpec(qiskit.QuantumCircuit) config = backend.configuration() if config.local: device_type = DeviceType.LOCAL_SIMULATOR elif config.simulator: device_type = DeviceType.SIMULATOR else: device_type = DeviceType.QPU return TargetProfile( device_id=backend.name, device_type=device_type, num_qubits=config.n_qubits, program_spec=program_spec, instance=backend._instance, max_shots=config.max_shots, provider_name="IBM", ) def get_devices( self, operational=True, **kwargs ) -> list["qbraid.runtime.qiskit.QiskitBackend"]: """Returns the IBM Quantum provider backends.""" backends = self.runtime_service.backends(operational=operational, **kwargs) program_spec = ProgramSpec(qiskit.QuantumCircuit) return [ QiskitBackend( profile=self._build_runtime_profile(backend, program_spec=program_spec), service=self.runtime_service, ) for backend in backends ] def get_device( self, device_id: str, instance: Optional[str] = None ) -> "qbraid.runtime.qiskit.QiskitBackend": """Returns the IBM Quantum provider backends.""" backend = self.runtime_service.backend(device_id, instance=instance) return QiskitBackend( profile=self._build_runtime_profile(backend), service=self.runtime_service ) def least_busy( self, simulator=False, operational=True, **kwargs ) -> "qbraid.runtime.qiskit.QiskitBackend": """Return the least busy IBMQ QPU.""" backend = self.runtime_service.least_busy( simulator=simulator, operational=operational, **kwargs ) return QiskitBackend( profile=self._build_runtime_profile(backend), service=self.runtime_service )