دمج موارد الحوسبة الكمومية الخارجية مع Qiskit
صُمِّم Qiskit SDK ليدعم الأطراف الثالثة في إنشاء مزوّدي موارد كمومية خارجيين.
هذا يعني أن أي مؤسسة تطوّر أو تنشر موارد حوسبة كمومية يمكنها دمج خدماتها مع Qiskit والاستفادة من قاعدة مستخدميه.
يتطلب ذلك إنشاء حزمة تدعم طلبات موارد الحوسبة الكمومية وتُعيدها إلى المستخدم.
علاوة على ذلك، يجب أن تتيح الحزمة للمستخدمين إرسال المهام واسترجاع نتائجها من خلال تطبيق يعتمد كائنات 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 وغيرها. يجب أن توفر هذه الواجهات، كحدٍّ أدنى، طريقة للتنفيذ والاستعلام عن حالة المهمة واسترجاع نتائجها.
للتعامل مع حالة المهمة ونتائجها، يوفر Qiskit SDK الكائنات 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