المحاكاة الفعّالة لدوائر المُثبِّت باستخدام Qiskit Aer primitives
إصدارات الحزم
الكود في هذه الصفحة جرى تطويره باستخدام المتطلبات التالية. ننصح باستخدام هذه الإصدارات أو ما هو أحدث منها.
qiskit[all]~=2.3.0
qiskit-aer~=0.17
تُوضح هذه الصفحة كيفية استخدام Qiskit Aer primitives لمحاكاة دوائر المُثبِّت بكفاءة عالية، بما في ذلك تلك التي تخضع لضوضاء Pauli.
دوائر المُثبِّت، المعروفة أيضاً بدوائر Clifford، هي فئة مُقيَّدة مهمة من الدوائر الكمومية يمكن محاكاتها بكفاءة على الحواسيب الكلاسيكية. ثمة عدة طرق متكافئة لتعريف دوائر المُثبِّت. أحد هذه التعريفات هو أن دائرة المُثبِّت هي دائرة كمومية تتكون حصراً من البوابات التالية:
لاحظ أنه باستخدام Hadamard وS، يمكننا بناء أي بوابة دوران Pauli (، ، و) التي تكون زاويتها ضمن المجموعة (حتى الطور العام)، لذا يمكننا تضمين هذه البوابات في التعريف أيضاً.
دوائر المُثبِّت مهمة لدراسة تصحيح أخطاء الكم. كما أن قابليتها للمحاكاة الكلاسيكية تجعلها مفيدة للتحقق من مخرجات الحواسيب الكمومية. على سبيل المثال، افترض أنك تريد تنفيذ دائرة كمومية تستخدم 100 Qubit على حاسوب كمومي. كيف تعرف أن الحاسوب الكمومي يعمل بشكل صحيح؟ إن الدائرة الكمومية على 100 Qubit تتجاوز قدرات المحاكاة الكلاسيكية المباشرة. من خلال تعديل دائرتك لتصبح دائرة مُثبِّت، يمكنك تشغيل دوائر على الحاسوب الكمومي تمتلك بنية مشابهة لدائرتك المطلوبة، لكنك تستطيع محاكاتها على حاسوب كلاسيكي. من خلال التحقق من مخرجات الحاسوب الكمومي على دوائر المُثبِّت، يمكنك اكتساب الثقة بأنه يعمل بشكل صحيح على الدوائر غير المُثبِّتة أيضاً. راجع Evidence for the utility of quantum computing before fault tolerance للاطلاع على مثال عملي لهذه الفكرة.
تُبيّن المحاكاة الدقيقة والمشوَّشة مع Qiskit Aer primitives كيفية استخدام Qiskit Aer لإجراء محاكاة دقيقة ومشوَّشة للدوائر الكمومية العامة. لنأخذ مثال الدائرة المستخدمة في تلك المقالة، وهي دائرة من 8 Qubits مبنية باستخدام efficient_su2:
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer
from qiskit.circuit.library import efficient_su2
n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")
باستخدام Qiskit Aer، تمكنا من محاكاة هذه الدائرة بسهولة. لكن افترض أننا رفعنا عدد الـ Qubits إلى 500:
n_qubits = 500
circuit = efficient_su2(n_qubits)
# don't try to draw the circuit because it's too large
نظراً لأن تكلفة محاكاة الدوائر الكمومية تتزايد بشكل أسي مع عدد الـ Qubits، فإن دائرة بهذا الحجم الكبير تتجاوز عموماً قدرات حتى المحاكي عالي الأداء مثل Qiskit Aer. تصبح المحاكاة الكلاسيكية للدوائر الكمومية العامة غير قابلة للتنفيذ عندما يتجاوز عدد الـ Qubits ما بين 50 و100 Qubit تقريباً. ومع ذلك، لاحظ أن دائرة efficient_su2 تتضمن معاملات لزوايا بوابات و. إذا كانت جميع هذه الزوايا ضمن المجموعة ، فإن الدائرة تكون دائرة مُثبِّت، ويمكن محا كاتها بكفاءة!
في الخلية التالية، نُشغِّل الدائرة مع Sampler primitive المدعوم بمحاكي دائرة المُثبِّت، باستخدام معاملات مختارة عشوائياً بحيث تكون الدائرة مضمونة كدائرة مُثبِّت.
import numpy as np
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import SamplerV2 as Sampler
measured_circuit = circuit.copy()
measured_circuit.measure_all()
rng = np.random.default_rng(1234)
params = rng.choice(
[0, np.pi / 2, np.pi, 3 * np.pi / 2],
size=circuit.num_parameters,
)
# Initialize a Sampler backed by the stabilizer circuit simulator
exact_sampler = Sampler(
options=dict(backend_options=dict(method="stabilizer"))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(
1, AerSimulator(method="stabilizer")
)
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params)
job = exact_sampler.run([pub])
result = job.result()
pub_result = result[0]
counts = pub_result.data.meas.get_counts()
يدعم محاكي دائرة المُثبِّت أيضاً المحاكاة المشوَّشة، لكن لفئة مُقيَّدة فقط من نماذج الضوضاء. تحديداً، يجب أن تتسم أي ضوضاء كمومية بقناة خطأ Pauli. يندرج خطأ الإزالة المتجانسة ضمن هذه الفئة، لذا يمكن محاكاته أيضاً. كما يمكن محاكاة قنوات الضوضاء الكلاسيكية مثل خطأ القراءة.
تُشغِّل خلية الكود التالية المحاكاة ذاتها كما في ا لسابق، لكن هذه المرة مع تحديد نموذج ضوضاء يُضيف خطأ إزالة متجانسة بنسبة 2% لكل بوابة CX، إضافة إلى خطأ قراءة يقلب كل بت مقروء باحتمالية 5%.
from qiskit_aer.noise import NoiseModel, depolarizing_error, ReadoutError
noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
bit_flip_prob = 0.05
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)
noise_model.add_all_qubit_readout_error(
ReadoutError(
[
[1 - bit_flip_prob, bit_flip_prob],
[bit_flip_prob, 1 - bit_flip_prob],
]
)
)
noisy_sampler = Sampler(
options=dict(
backend_options=dict(method="stabilizer", noise_model=noise_model)
)
)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
counts = pub_result.data.meas.get_counts()
الآن، لنستخدم Estimator primitive المدعوم بمحاكي المُثبِّت لحساب القيمة المتوقعة للمُراقِب . بفضل البنية الخاصة لدوائر المُثبِّت، من المرجح جداً أن تكون النتيجة 0.
from qiskit.quantum_info import SparsePauliOp
from qiskit_aer.primitives import EstimatorV2 as Estimator
observable = SparsePauliOp("Z" * n_qubits)
exact_estimator = Estimator(
options=dict(backend_options=dict(method="stabilizer")),
)
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.0
الخطوات التالية
- لمحاكاة الدوائر مع Qiskit Aer، راجع المحاكاة الدقيقة والمشوَّشة مع Qiskit Aer primitives.
- راجع توثيق Qiskit Aer.