Přeskočit na hlavní obsah

Integrace externích kvantových zdrojů s Qiskitem

Qiskit SDK je navržen tak, aby umožňoval třetím stranám vytvářet externí poskytovatele kvantových zdrojů.

To znamená, že jakákoli organizace, která vyvíjí nebo provozuje kvantové výpočetní zdroje, může integrovat své služby do Qiskitu a využít jeho uživatelskou základnu.

K tomu je potřeba vytvořit balíček, který podporuje požadavky na kvantové výpočetní zdroje a vrací je uživateli.

Balíček musí navíc umožňovat uživatelům odesílat úlohy a získávat jejich výsledky prostřednictvím implementace objektů qiskit.primitives.

Poskytování přístupu k Backend

Aby mohli uživatelé transpilovat a spouštět objekty QuantumCircuit pomocí externích zdrojů, musí vytvořit instanci objektu obsahujícího Target, který poskytuje informace o omezeních QPU, jako je jeho konektivita, základní Gate a počet Qubitů. Toto lze zpřístupnit prostřednictvím rozhraní podobného QiskitRuntimeService, přes které může uživatel posílat požadavky na QPU. Tento objekt by měl minimálně obsahovat Target, ale jednodušším přístupem by bylo vrátit instanci BackendV2.

Příklad implementace může vypadat přibližně takto:

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

Poskytování rozhraní pro spouštění

Kromě poskytování služby vracející konfigurace hardwaru může služba zpřístupňující externí QPU zdroje také podporovat spouštění kvantových pracovních zátěží. Tuto schopnost lze zpřístupnit vytvořením implementací rozhraní primitiv Qisskitu, například BasePrimitiveJob, BaseEstimatorV2 a BaseSamplerV2 a dalších. Tato rozhraní by měla minimálně poskytovat metodu pro spouštění, dotazování na stav úlohy a vracení výsledků úlohy.

Pro zpracování stavu úloh a výsledků poskytuje Qiskit SDK objekty DataBin, PubResult, PrimitiveResult a BasePrimitiveJob, které by měly být použity.

Více informací najdeš v dokumentaci API modulu qiskit.primitives a také v referenčních implementacích BackendEstimatorV2 a BackendSampleV2.

Příklad implementace primitiva Estimator může vypadat takto:

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

A příklad implementace primitiva Sampler může vypadat takto:

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