Skip to main content
IBM Quantum Platform

Integra recursos cuánticos externos con Qiskit

La web Qiskit SDK está pensada para que terceros puedan crear proveedores externos de recursos cuánticos.

Esto significa que cualquier organización que desarrolle o despliegue recursos de computación cuántica puede integrar sus servicios en Qiskit y aprovechar su base de usuarios.

Para ello, es necesario crear un paquete que admita solicitudes de recursos informáticos cuánticos y los devuelva al usuario.

Además, el paquete debe permitir a los usuarios enviar trabajos y recuperar sus resultados mediante una implementación de los objetos qiskit.primitives .


Proporcionar acceso a los backends

Para que los usuarios puedan transpilar y ejecutar objetos de QuantumCircuit utilizando recursos externos, necesitan instanciar un objeto que contenga un Target que proporciona información sobre las restricciones de una QPU, como su conectividad, puertas base y número de qubits. Esto puede proporcionarse a través de una interfaz similar a la QiskitRuntimeService a través de la cual un usuario puede realizar solicitudes de una QPU. Este objeto debería, como mínimo, contener un Target, pero un enfoque más sencillo sería devolver una BackendV2 instancia.

Un ejemplo de implementación puede ser algo así:

from qiskit.transpiler import Target
from qsikit.providers import BackendV2

class ProviderService:
    """ Class for interacting with a provider's service"""

    def __init__(
        self,
        #Receive arguments for authentication/instantiation
    ):
        """ Initiate a connection with the provider service, given some method 
                of authentication """

    def return_target(name: Str) -> Target:
        """ Interact with the service and return a Target object """
        return target

    def return_backend(name: Str) -> BackendV2:
        """ Interact with the service and return a BackendV2 object """
        return backend

Proporcionar una interfaz para la ejecución

Además de proporcionar un servicio que devuelva configuraciones de hardware, un servicio que proporcione acceso a recursos QPU externos también podría soportar la ejecución de cargas de trabajo cuánticas. La exposición de esta capacidad puede realizarse mediante la creación de implementaciones de las interfaces Qiskit primitives; por ejemplo, las interfaces BasePrimitiveJob, BaseEstimatorV2 y BaseSamplerV2 entre otras. Como mínimo, estas interfaces deben ser capaces de proporcionar un método para la ejecución, la consulta del estado del trabajo y la devolución de los resultados del trabajo.

Para gestionar el estado y los resultados de los trabajos, Qiskit SDK proporciona una función DataBin, PubResult, PrimitiveResulty BasePrimitiveJob .

Consulte la documentación de la API qiskit.primitives , así como las implementaciones de referencia BackendEstimatorV2 y BackendSampleV2 para más información.

Un ejemplo de implementación de la primitiva Estimator puede tener este aspecto:

from qiskit.primitives import BaseEstimatorV2, BaseSamplerV2, EstimatorPubLike
from qiskit.primitives import DataBin, PubResult, PrimitiveResult, BasePrimitiveJob
from qiskit.providers import BackendV2

class EstimatorImplementation(BaseEstimatorV2):
    """ Class for interacting with the provider's Estimator service """

    def __init__(
        self,
        *,
        backend: BackendV2,
        options: dict
        # Receive other arguments to instantiate an Estimator primitive with the service
    ):
        self._backend = backend
        self._options = options
        self._default_precision = 0.01

    @property
    def backend(self) -> BackendV2:
        """ Return the backend """
        return self._backend

    def run(
        self, pubs: Iterable[EstimatorPubLike], *, precision: float | None = None
    ) -> BasePrimitiveJob[PrimitiveResult[PubResult]]:
    """ Steps to implement: 
            1. Define a default precision if none is given 
            2. Validate pub format
            3. Instantiate an object which inherits from BasePrimitiveJob 
                containing pub and runtime information
            4. Send the job to the execution service of the provider
    """
    job = BasePrimitiveJob(pubs, precision)
    job_with_results = job.submit()
    return job_with_results

Y una implementación de la primitiva Sampler puede tener este aspecto:

class SamplerImplementation(BaseSamplerV2):
    """ Class for interacting with the provider's Sampler service """

    def __init__(
        self,
        *,
        backend: BackendV2,
        options: dict
        # Receive other arguments to instantiate an Estimator primitive with the service
    ):
        self._backend = backend
        self._options = options
        self._default_shots = 1024

    @property
    def backend(self) -> BackendV2:
        """ Return the Sampler's backend """
        return self._backend

    def run(
        self, pubs: Iterable[SamplerPubLike], *, shots: int | None = None
    ) -> BasePrimitiveJob[PrimitiveResult[SamplerPubResult]]:
    """ Steps to implement: 
            1. Define a default number of shots if none is given 
            2. Validate pub format
            3. Instantiate an object which inherits from BasePrimitiveJob 
                containing pub and runtime information
            4. Send the job to the execution service of the provider
            5. Return the data in some format
    """
    job = BasePrimitiveJob(pubs, shots)
    job_with_results = job.submit()
    return job_with_results
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.