שילוב משאבי קוונטום חיצוניים עם Qiskit
ה-SDK של Qiskit בנוי כדי לאפשר לצדדים שלישיים ליצור ספקים חיצוניים של משאבי קוונטום.
כלומר, כל ארגון שמפתח או מפעיל משאבי מחשוב קוונטי יכול לשלב את השירותים שלו ב-Qiskit ולנצל את בסיס המשתמשים שלו.
כדי לעשות זאת, צריך ליצור חבילה שתומכת בבקשות למשאבי מחשוב קוונטי ומחזירה אותן למשתמש.
בנוסף, החבילה חייבת לאפשר למשתמשים לשלוח jobs ולאחזר את תוצאותיהם דרך מימוש של אובייקטי qiskit.primitives.
מתן גישה ל-Backends
כדי שמשתמשים יוכלו לבצע transpile ולהריץ אובייקטי QuantumCircuit תוך שימוש במשאבים חיצוניים, עליהם ליצור מופע של אובייקט המכיל Target — שמספק מידע על אילוצי ה-QPU כגון קישוריות, שערי בסיס ומספר ה-Qubits. ניתן לספק זאת דרך ממשק הדומה ל-QiskitRuntimeService, שדרכו המשתמש יכול לשלוח בקשות ל-QPU. אובייקט זה צריך להכיל לפחות Target, אך גישה פשוטה יותר היא להחזיר מופע של BackendV2.
דוגמה למימוש עשויה להיראות כך:
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
מתן ממשק להרצה
בנוסף לספק שירות שמחזיר תצורות חומרה, שירות המספק גישה למשאבי QPU חיצוניים עשוי גם לתמוך בהרצת עומסי עבודה קוונטיים. חשיפת יכולת זו אפשרית על ידי יצירת מימושים של ממשקי ה-primitives של Qiskit — לדוגמה BasePrimitiveJob, BaseEstimatorV2 ו-BaseSamplerV2 ועוד. לכל הפחות, ממשקים אלה צריכים לספק שיטה להרצה, לשאילת סטטוס job ולהחזרת תוצאות ה-job.
לטיפול בסטטוס jobs ותוצאות, ה-SDK של Qiskit מספק את האובייקטים DataBin, PubResult, PrimitiveResult ו-BasePrimitiveJob.
ראו את תיעוד ה-API של qiskit.primitives וכן את מימושי הייחוס BackendEstimatorV2 ו-BackendSampleV2 למידע נוסף.
דוגמה למימוש של ה-primitive מסוג Estimator עשויה להיראות כך:
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
ודוגמה למימוש של ה-primitive מסוג Sampler עשויה להיראות כך:
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