انتقل إلى المحتوى الرئيسي

مقدمة إلى الأوليات (Primitives)

Package versions

The code on this page was developed using the following requirements. We recommend using these versions or newer.

qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
New execution model, now in beta release

The beta release of a new execution model is now available. The directed execution model provides more flexibility when customizing your error mitigation workflow. See the Directed execution model guide for more information.

لماذا أدخل Qiskit الأوليات؟

على غرار الأيام الأولى للحواسيب الكلاسيكية، حين كان على المطورين التعامل مع سجلات المعالج مباشرةً، كانت الواجهة الأولى للـ QPUs تُعيد البيانات الخام من الإلكترونيات الضابطة. لم يكن هذا مشكلة كبيرة حين كانت الـ QPUs في المختبرات ولا يصل إليها إلا الباحثون مباشرةً. إدراكًا بأن معظم المطورين لن يكونوا ملمّين — ولا ينبغي أن يكونوا — بكيفية تحليل هذه البيانات الخام إلى أصفار وآحاد، أدخل Qiskit الدالة backend.run، وهي أول مستوى تجريد للوصول إلى الـ QPUs عبر الحوسبة السحابية. أتاح ذلك للمطورين العمل بصيغ بيانات مألوفة والتركيز على الصورة الأكبر.

مع اتساع الوصول إلى الـ QPUs وتطور المزيد من الخوارزميات الكمية، برزت مجددًا الحاجة إلى مستوى تجريد أعلى. استجابةً لذلك، أدخل Qiskit واجهة الأوليات، المُحسَّنة لمهمتين أساسيتين في تطوير الخوارزميات الكمية: تقدير قيم التوقع (Estimator) وأخذ عينات من الدوائر (Sampler). الهدف مرة أخرى هو مساعدة المطورين على التركيز أكثر على الابتكار وأقل على تحويل البيانات. تحل واجهة الأوليات محل واجهة backend.run، إذ يوفر Sampler نفس الوصول المباشر إلى العتاد الذي كانت تتيحه backend.run.

ما هي الأولية (Primitive)؟

تُبنى أنظمة الحوسبة على طبقات متعددة من التجريد. تتيح لك التجريدات التركيز على مستوى معين من التفاصيل ذات الصلة بالمهمة التي بين يديك. كلما اقتربت من العتاد، قلّ مستوى التجريد الذي تحتاجه (مثلًا، قد تحتاج إلى نقل البيانات أو معالجتها على مستوى تعليمات المعالج). وكلما تعقّدت المهمة التي تريد تنفيذها، ارتفع مستوى التجريدات المستخدمة (مثلًا، قد تستعين بمكتبة برمجية لإجراء حسابات جبرية).

في هذا السياق، الأولية هي أصغر وحدة معالجة، اللبنة الأساسية الأبسط التي يمكن من خلالها بناء شيء مفيد لمستوى تجريد معين.

زاد التقدم الأخير في الحوسبة الكمية من الحاجة للعمل عند مستويات تجريد أعلى. مع تحرك هذا المجال نحو وحدات معالجة كمية (QPUs) أكبر وسير عمل أكثر تعقيدًا، يتحوّل التركيز من التفاعل مع إشارات الكيوبت الفردية إلى النظر إلى الأجهزة الكمية كأنظمة تؤدي المهام المطلوبة.

أكثر مهمتين شيوعًا في الحواسيب الكمية هما: أخذ عينات من الحالات الكمية وحساب قيم التوقع. هاتان المهمتان شكّلتا الدافع وراء تصميم أوليات Qiskit: Estimator وSampler.

  • يحسب Estimator قيم توقع المقاييس (observables) بالنسبة إلى الحالات التي تُهيئها الدوائر الكمية.
  • يأخذ Sampler عينات من سجل الإخراج الناتج عن تشغيل الدوائر الكمية.

باختصار، يُقرّب النموذج الحسابي الذي تقدمه أوليات Qiskit البرمجة الكمية خطوةً من حيث وصلت إليه البرمجة الكلاسيكية اليوم، حيث يقل التركيز على تفاصيل العتاد ويزيد على النتائج التي تسعى إلى تحقيقها.

تعريف الأوليات وتطبيقاتها

يوجد نوعان من أوليات Qiskit: الفئات الأساسية (base classes)، وتطبيقاتها (implementations). تُعرَّف أوليات Qiskit عبر فئات أساسية مفتوحة المصدر موجودة في حزمة Qiskit SDK (في وحدة qiskit.primitives). يمكن للمزودين (مثل Qiskit Runtime) استخدام هذه الفئات الأساسية لاشتقاق تطبيقاتهم الخاصة من Sampler وEstimator. سيتعامل معظم المستخدمين مع تطبيقات المزودين، لا مع الأوليات الأساسية مباشرةً.

الفئات الأساسية

BaseEstimatorV2 وBaseSamplerV2 - فئات أساسية مجردة تُعرّف واجهة مشتركة لتطبيق الأوليات. جميع الفئات الأخرى في وحدة qiskit.primitives ترث من هذه الفئات الأساسية. ينبغي للمطورين استخدامها إن كانوا مهتمين بإنشاء نموذج تنفيذ خاص بهم يعتمد على الأوليات لمزود محدد. قد تفيد هذه الفئات أيضًا من يريد إجراء معالجة مخصصة للغاية ويجد أن التطبيقات الحالية للأوليات بسيطة جدًا لاحتياجاته. لن يستخدم المستخدمون العاديون الفئات الأساسية مباشرةً.

التطبيقات

هذه هي تطبيقات الفئات الأساسية للأوليات:

  • توفر أوليات Qiskit Runtime (EstimatorV2 وSamplerV2) تطبيقًا أكثر تطورًا (مثلًا، بتضمين تخفيف الأخطاء) كخدمة سحابية. يُستخدم هذا التطبيق للوصول إلى عتاد IBM Quantum®، ويُوصَل إليه عبر IBM Qiskit Runtime.

  • StatevectorEstimator وStatevectorSampler - تطبيقات مرجعية للأوليات تستخدم المحاكي المدمج في Qiskit. بُنيت باستخدام وحدة Qiskit quantum_info، وتنتج نتائج مبنية على محاكاة متجه الحالة المثالية. يُوصَل إليها عبر Qiskit.

  • BackendEstimatorV2 وBackendSamplerV2 - يمكنك استخدام هذه الفئات "لتغليف" أي مورد حوسبة كمية في أولية. يتيح لك ذلك كتابة كود بأسلوب الأوليات لمزودين لا يملكون بعد واجهة مبنية على الأوليات. يمكن استخدام هذه الفئات تمامًا مثل Sampler وEstimator العاديين، باستثناء أنه ينبغي تهيئتها بمعامل إضافي backend لتحديد الحاسوب الكمي المُراد التشغيل عليه. يُوصَل إليها باستخدام Qiskit.

فوائد أوليات Qiskit

بفضل الأوليات، يستطيع مستخدمو Qiskit كتابة كود كمي لـ QPU محدد دون الحاجة إلى إدارة كل التفاصيل بشكل صريح. علاوةً على ذلك، بفضل طبقة التجريد الإضافية، قد تتمكن من الوصول بسهولة أكبر إلى الإمكانات المتقدمة لعتاد مزود معين. فمثلًا، مع أوليات Qiskit Runtime، يمكنك الاستفادة من أحدث التطورات في تخفيف الأخطاء وقمعها بمجرد ضبط خيارات مثل resilience_level الخاص بالأولية، بدلًا من بناء تطبيقك الخاص لهذه التقنيات.

بالنسبة لمزودي العتاد، يعني تطبيق الأوليات بشكل أصيل أنه يمكنك تزويد مستخدميك بطريقة أكثر سهولةً "من الصندوق" للوصول إلى ميزات عتادك كتقنيات المعالجة اللاحقة المتقدمة. وهذا يجعل من السهل على مستخدميك الاستفادة من أفضل إمكانات عتادك.

تفاصيل الأوليات

كما ذُكر سابقًا، تُنشأ جميع الأوليات من الفئات الأساسية؛ لذا فإنها تشترك في نفس البنية العامة وطريقة الاستخدام. مثلًا، صيغة المدخلات لجميع أوليات Estimator واحدة. غير أن هناك اختلافات في التطبيقات تجعل كلًا منها فريدًا.

ملاحظة

نظرًا لأن معظم المستخدمين يصلون إلى أوليات Qiskit Runtime، فإن الأمثلة في بقية هذا القسم مبنية على أوليات Qiskit Runtime.

Estimator

تحسب الأولية Estimator قيم التوقع لمقياس واحد أو أكثر بالنسبة إلى الحالات التي تُهيئها الدوائر الكمية. يمكن أن تكون الدوائر ذات معاملات (parametrized)، شريطة توفير قيم المعاملات أيضًا كمدخلات للأولية.

المدخل هو مصفوفة من PUBs. كل PUB بالصيغة:

(<single circuit>, <one or more observables>, <optional one or more parameter values>, <optional precision>),

حيث يمكن أن تكون parameter values الاختيارية قائمةً أو معاملًا واحدًا. تدعم تطبيقات Estimator المختلفة خيارات إعداد متنوعة. إن احتوى المدخل على قياسات، فسيتم تجاهلها.

المخرج هو PubResult يحتوي على قيم التوقع المحسوبة لكل زوج والأخطاء المعيارية الخاصة بها، في صيغة PubResult. يحتوي كل PubResult على بيانات وبيانات وصفية.

يجمع Estimator عناصر المقاييس وقيم المعاملات باتباع قواعد البث (broadcasting rules) الخاصة بـ NumPy كما هو موصوف في موضوع مدخلات ومخرجات الأوليات.

مثال:

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime
# This cell is hidden from users, it creates the circuits and observables to run

from qiskit_ibm_runtime import EstimatorV2, SamplerV2, QiskitRuntimeService
from qiskit.circuit.random import random_circuit
from qiskit.circuit import Parameter
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
import numpy as np

service = QiskitRuntimeService()
backend = service.least_busy()
phi = Parameter("phi")

circuit1 = random_circuit(10, 5, seed=12345)
circuit1.rzz(phi, 1, 2)
observable1 = SparsePauliOp.from_sparse_list(
[("ZXYZ", [1, 2, 3, 4], 1)], num_qubits=10
)
param_values1 = np.random.uniform(size=5).T

circuit2 = random_circuit(10, 5, seed=12345)
circuit2.rzz(phi, 1, 2)
observable2 = SparsePauliOp.from_sparse_list(
[("XZYX", [1, 2, 3, 4], 1)], num_qubits=10
)
param_values2 = np.random.uniform(size=5).T

shots1 = 164
shots2 = 1024

pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
circuit1 = pm.run(circuit1)
circuit2 = pm.run(circuit2)
observable1 = observable1.apply_layout(circuit1.layout)
observable2 = observable2.apply_layout(circuit2.layout)
estimator = EstimatorV2(mode=backend)
estimator_job = estimator.run(
[
(circuit1, observable1, param_values1),
(circuit2, observable2, param_values2),
]
)

Sampler

المهمة الأساسية لـ Sampler هي أخذ عينات من سجل الإخراج الناتج عن تشغيل دائرة كمية واحدة أو أكثر. يمكن أن تكون الدوائر المدخلة ذات معاملات، شريطة توفير قيم المعاملات أيضًا كمدخلات للأولية.

المدخل هو PUBs واحد أو أكثر، بالصيغة:

(<single circuit>, <one or more optional parameter value>, <optional shots>),

حيث يمكن أن تكون هناك عناصر متعددة لـ parameter values، وكل عنصر يمكن أن يكون مصفوفةً أو معاملًا واحدًا، بحسب الدائرة المختارة. علاوةً على ذلك، يجب أن يحتوي المدخل على قياسات.

المخرج هو أعداد (counts) أو قياسات لكل لقطة (per-shot measurements) على شكل كائنات PubResult، دون أوزان. غير أن فئة النتيجة تحتوي على توابع تُعيد عينات موزونة، كالأعداد. راجع مدخلات ومخرجات الأوليات للاطلاع على التفاصيل الكاملة.

مثال:

# This cell is hidden from users, add measurement instructions to circuits
circuit1.measure_active()
circuit2.measure_active()
sampler = SamplerV2(mode=backend)
sampler_job = sampler.run(
[
(circuit1, param_values1, shots1),
(circuit2, param_values2, shots2),
]
)

الخطوات التالية

Recommendations