المحاكاة الدقيقة والمحاكاة بالضوضاء باستخدام Qiskit Aer primitives
إصدارات الحزم
تم تطوير الكود في هذه الصفحة باستخدام المتطلبات التالية. ننصح باستخدام هذه الإصدارات أو ما هو أحدث منها.
qiskit[all]~=2.3.0
qiskit-aer~=0.17
يوضح المحاكاة الدقيقة باستخدام Qiskit primitives كيفية استخدام الـ primitives المرجعية المضمّنة في Qiskit لإجراء محاكاة دقيقة للدوائر الكمومية. تعاني المعالجات الكمومية الحالية من أخطاء أو ضوضاء، لذا فإن نتائج المحاكاة الدقيقة لا تعكس بالضرورة النتائج التي ستحصل عليها عند تشغيل الدوائر على أجهزة حقيقية. في حين أن الـ primitives المرجعية في Qiskit لا تدعم نمذجة الضوضاء، يتضمن Qiskit Aer تطبيقات للـ primitives تدعم نمذجة الضوضاء. Qiskit Aer هو محاكي دوائر كمومية عالي الأداء يمكنك استخدامه بدلاً من الـ primitives المرجعية للحصول على أداء أفضل وميزات إضافية. وهو جزء من Qiskit Ecosystem. في هذا المقال، نستعرض استخدام Qiskit Aer primitives للمحاكاة الدقيقة والمحاكاة بالضوضاء.
- يُشترط استخدام الإصدار
qiskit-aerv0.14 أو أحدث. - رغم أن Qiskit Aer primitives تُطبّق واجهات الـ primitives، إلا أنها لا توفر نفس الخيارات المتاحة في Qiskit Runtime primitives. فمستوى المرونة (Resilience level)، على سبيل المثال، غير متاح في Qiskit Aer primitives.
- راجع توثيق AerSimulator للاطلاع على تفاصيل خيارات أساليب المحاكاة التي يدعمها Aer.
لاستكشاف المحاكاة الدقيقة والمحاكاة بالضوضاء، أنشئ دائرة مثال على ثمانية Qubits:
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit.circuit.library import efficient_su2
n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")
تحتوي هذه الدائرة على معاملات تمثّل زوايا الدوران لبوابات و . عند محاكاة هذه الدائرة، نحتاج إلى تحديد قيم صريحة لهذه المعاملات. في الخلية التالية، نحدد بعض القيم لهذه المعاملات ونستخدم الـ Estimator primitive من Qiskit Aer لحساب القيمة المتوقعة الدقيقة للمؤثر .
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import EstimatorV2 as Estimator
observable = SparsePauliOp("Z" * n_qubits)
params = [0.1] * circuit.num_parameters
exact_estimator = Estimator()
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value
0.8870140234256602
الآن، لنقم بتهيئة نموذج ضوضاء يتضمن خطأ depolarizing بنسبة 2% على كل بوابة CX. في الواقع العملي، الأخطاء الناشئة عن بوابات الـ Qubitين، وهي بوابات CX هنا، هي المصدر الرئيسي للخطأ عند تشغيل الدائرة. راجع بناء نماذج الضوضاء للاطلاع على نظرة عامة حول إنشاء نماذج الضوضاء في Qiskit Aer.
في الخلية التالية، نبني Estimator يدمج نموذج الضوضاء هذا ونستخدمه لحساب القيمة المتوقعة للمؤثر.
from qiskit_aer.noise import NoiseModel, depolarizing_error
noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)
noisy_estimator = Estimator(
options=dict(backend_options=dict(noise_model=noise_model))
)
job = noisy_estimator.run([pub])
result = job.result()
pub_result = result[0]
noisy_value = float(pub_result.data.evs)
noisy_value
0.7247404214143528
كما ترى، القيمة المتوقعة في ظل وجود الضوضاء بعيدة جداً عن القيمة الصحيحة. في الواقع العملي، يمكنك توظيف مجموعة من تقنيات تخفيف الأخطاء لمواجهة تأثيرات الضوضاء، لكن الحديث عن هذه التقنيات يخرج عن نطاق هذا المقال.
للحصول على فكرة تقريبية عن كيفية تأثير الضوضاء على النتيجة النهائية، تأمّل نموذج الضوضاء لدينا، الذي يضيف خطأ depolarizing بنسبة 2% إلى كل بوابة CX. يُعرَّف خطأ Depolarizing بالاحتمال على أنه قناة كمومية لها التأثير التالي على مصفوفة الكثافة :
حيث هو عدد الـ Qubits، وهو 2 في هذه الحالة. أي أنه باحتمال ، تُستبدل الحالة بالحالة المختلطة تماماً، وتُحفظ الحالة باحتمال . بعد تطبيقاً لقناة depolarizing، سيكون احتمال الحفاظ على الحالة هو . لذا، نتوقع أن يتراجع احتمال الحفاظ على الحالة الصحيحة في نهاية المحاكاة بشكل أسّي مع زيادة عدد بوابات CX في دائرتنا.
لنحسب عدد بوابات CX في دائرتنا ونحسب . نس تدعي count_ops للحصول على قاموس يربط أسماء البوابات بعدد مرات ظهورها، ثم نسترجع القيمة المقابلة لبوابة CX.
cx_count = circuit.count_ops()["cx"]
(1 - cx_depolarizing_prob) ** cx_count
0.6542558123199923
هذه القيمة، 65%، تعطي تقديراً تقريبياً لاحتمال صحة حالتنا النهائية. وهي تقدير متحفظ لأنها لا تأخذ بعين الاعتبار الحالة الابتدائية للمحاكاة.
تُظهر خلية الكود التالية كيفية استخدام الـ Sampler primitive من Qiskit Aer للأخذ بالعينات من الدائرة ذات الضوضاء. نحتاج إلى إضافة قياسات إلى الدائرة قبل تشغيلها مع الـ Sampler primitive.
from qiskit_aer.primitives import SamplerV2 as Sampler
measured_circuit = circuit.copy()
measured_circuit.measure_all()
noisy_sampler = Sampler(
options=dict(backend_options=dict(noise_model=noise_model))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params, 100)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
pub_result.data.meas.get_counts()
{'00100000': 1,
'00000000': 65,
'10101000': 1,
'10000000': 5,
'00001000': 1,
'00000110': 2,
'11110010': 1,
'00000011': 3,
'01010000': 3,
'11000000': 3,
'01111000': 1,
'01000000': 2,
'00000010': 1,
'01100000': 1,
'00011000': 1,
'00111100': 1,
'00010100': 1,
'00001111': 1,
'00110000': 1,
'01100101': 1,
'00000100': 1,
'10100000': 1,
'00000001': 1,
'11010000': 1}
الخطوات التالية
- لمحاكاة دوائر صغيرة وبسيطة، راجع المحاكاة الدقيقة باستخدام Qiskit primitives.
- راجع توثيق Qiskit Aer.