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

تجربتك الكمومية الأولى

مقدمة

في الفيديو التالي، تأخذك أوليفيا لينز عبر محتوى هذا الدرس. بدلاً من ذلك، يمكنك فتح فيديو يوتيوب الخاص بهذا الدرس في نافذة منفصلة.

بحلول هذه المرحلة، شغّلت دائرتك الكمومية الأولى وتعلّمت أساسيات الحوسبة الكمومية: كيف تُمثَّل الحالات الكمية، وكيف تعمل البوابات على تلك الحالات، وكيف تنخرط الميزات الكمومية كالتراكب والتشابك في ذلك. الآن حان وقت تطبيق كل هذا وحل أول مسألة على حاسوب كمومي.

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

في هذا الدرس، سنتّبع هذا المبدأ لمحاكاة التفاعل بين غزلَين، يمكنك التفكير فيهما كمغناطيسين صغيرَين. واعتماداً على إشارة تفاعلهما، قد يُفضّلان التوافق والإشارة في نفس الاتجاه، أو التعاكس والإشارة في اتجاهَين متعاكسَين. سنركز على الحالة الأخيرة لأنها كثيراً ما تؤدي إلى سلوك أكثر إثارة — وأكثر تحدياً. بمجرد أن نفهم هذا النظام الصغير ثنائي الـ Qubit، سنُظهر كيف تتوسع نفس الأفكار لتمكين الحواسيب الكمومية من الاستفادة من تكاملها الأسي عند محاكاة أنظمة الغزل الكبيرة.

مغناطيسان متفاعلان

في هذه المسألة، سنستخدم Qubitين، واحدة لكل غزل في نموذجنا. يمكن لكل غزل أن يشير إلى الأعلى (حالة الـ Qubit 0|0\rangle)، أو إلى الأسفل (حالة الـ Qubit 1|1\rangle)، أو في تراكب من الحالتين.

إذا كان للغزلَين تفاعل مغناطيسي مضاد، فهذا يعني أنهما يريدان التعاكس، لذا حين يشير أحدهما إلى الأعلى، يريد الآخر أن يشير إلى الأسفل، والعكس صحيح.

لنفترض أن هناك أيضاً مجالاً مغناطيسياً يشير من اليسار إلى اليمين في نظامنا. لأن هذا المجال يشير عبر الاتجاه المعتاد لأعلى-أسفل للغزول، يُسمى مجالاً مستعرضاً. يمكن لهذا المجال قلب الغزول، مما يجعل تهيئة أدنى طاقة تراكباً محدداً من ترتيبات الغزل أعلى-أسفل بدلاً من أي نمط غزل محدد.

يمكننا وصف كل هذه التأثيرات باستخدام كائن رياضي يُسمى الهاميلتوني. يخبرنا الهاميلتوني بطاقة النظام لتهيئة معينة من الغزول:

H=JZ1Z0+hx(X1+X0)H = J Z_1 Z_0 + h_x (X_1 + X_0)

حيث JJ معامل يتحكم في قوة التفاعل بين الغزول وhxh_x معامل لقوة المجال المغناطيسي الخارجي. يُكافئ Z1Z0Z_1 Z_0 أو يُعاقب الغزول بناءً على ما إذا كانت متوافقة أو متعاكسة، ويمثّل X0X_0 وX1X_1 تأثير قلب الغزل للمجال المغناطيسي.

في الفيزياء، تميل الأنظمة إلى الاستقرار في الحالة ذات أدنى طاقة ممكنة، وتُسمى الحالة الأرضية. إيجاد هذه الحالة ذات الطاقة الدنيا مسألة شائعة، لكنها تتطلب أساليب تحسين تتجاوز نطاق هذا الدرس.

بدلاً من ذلك، سنطرح سؤالاً أبسط: إذا هيّأنا الغزول في حالة معينة، فما طاقة تلك الحالة؟

للإجابة على هذا، سنقوم بـ:

  1. تهيئة الغزول في حالة من اختيارنا
  2. قياس طاقة تلك الحالة باستخدام الهاميلتوني أعلاه

هذا بالضبط نوع الحساب الذي يظهر داخل خوارزميات كمومية أكبر، كالخوارزميات التغايرية، التي يمكنك استكشافها في دورات لاحقة.

التنفيذ بـ Qiskit

قبل الشروع في كتابة الكود، نحتاج إلى بعض السياق. حين نشغّل دائرة كمومية، ننتهي دائماً بقياس الـ Qubits. لكن ثمة نوعان مختلفان من الأسئلة التي قد نريد طرحها حول نتيجة ذلك القياس: أحياناً نريد فقط معرفة ما هي حالة الـ Qubit. وفي أحيان أخرى نريد معرفة، بالنظر إلى الحالة الكمومية، ما قيمة كمية فيزيائية معينة، كالطاقة؟

في Qiskit، يُعالَج هذان النوعان من الأسئلة بأداتَين مختلفتَين تُسميان العناصر الأساسية (primitives).

يجيب Sampler على النوع الأول من الأسئلة. يشغّل الدائرة عدة مرات ويخبرنا بمدى تكرار قياس كل نتيجة محتملة، مثل 00 أو 01 أو 10 أو 11. النتيجة رسم بياني يُظهر احتمال كل نتيجة قياس.

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

لمساعدتك على فهم متى ولماذا نستخدم كل من هذه الأدوات، سنمر عبر سيرَي عمل كاملَين (يُسميان «أنماط Qiskit») مُطبَّقَين على النظام ثنائي الـ Qubit ذاته.

سير عمل أنماط Qiskit

سير عمل أنماط Qiskit إطار عام نستخدمه لحل المسائل الكمومية بـ Qiskit. يُقسّم مهمة الحوسبة الكمومية إلى أربع خطوات:

  1. تعيين المسألة إلى نموذج يمكن تمثيله بدوائر كمومية
  2. تحسين الدائرة للتشغيل على Backend محدد
  3. تنفيذ الدائرة المحسّنة على الـ Backend المختار
  4. المعالجة اللاحقة لبيانات القياس الخام

التجربة 1: استخدام Sampler لقياس الحالة

التعيين

بشكل عام، خطوة التعيين هي التي نحدد فيها كيفية تمثيل مسألة واقعية من حيث الـ Qubits والمؤثرات والقياسات. في كثير من التطبيقات، هذه هي الجزء الأصعب والأكثر تعقيداً من سير العمل — حتى الأسئلة البسيطة، كـ «ماذا يمثّل كل Qubit؟»، ليست دائماً لها إجابات مباشرة.

لكن في هذه التجربة، التعيين بسيط متعمَّداً. كل درجة حرية فيزيائية تُعيَّن مباشرة إلى Qubit واحدة. بسبب هذا التطابق الواحد-لواحد، تُختزل خطوة التعيين إلى اختيار الحالة الكمومية التي نريد تهيئتها وكتابة دائرة تُهيّئ تلك الحالة وتقيسها.

هنا، سنهيّئ حالة Bell متشابكة، مشابهة للتي صنعناها في الدرس الأول من هذه الدورة:

Ψ=12(1001)\vert\Psi\rangle = \frac{1}{\sqrt{2}}(\vert 10\rangle - \vert 01\rangle)
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
# Import Qiskit primitives
from qiskit import QuantumCircuit

# Make state
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.x(1)
qc.z(0)

# Measure state
qc.measure_all()

# Draw circuit
qc.draw("mpl")

Output of the previous code cell

التحسين

قبل تشغيل دائرتنا على حاسوب كمومي (أو محاكٍ إذا استنفدت وقتك المجاني على الحواسيب الكمومية الحقيقية للشهر)، نحتاج إلى تحضيرها للتنفيذ. تُسمى هذه الخطوة التحسين. (ملاحظة: قد يكون هذا الاستخدام لكلمة «التحسين» مربكاً. في الحوسبة الكمومية، تشير مسائل التحسين إلى فئة محددة من المسائل. هنا نستخدم التحسين لوصف خطوة تحضير مطلوبة يمر بها كل Circuit كمومية قبل أن يمكن تشغيله بكفاءة على الأجهزة.)

خلال التحسين:

  1. نختار الـ Backend — إما حاسوب كمومي حقيقي أو محاكٍ.
  2. نُسنِد Qubits الدائرة إلى Qubits فيزيائية على الجهاز.
  3. نُعيد كتابة الدائرة باستخدام البوابات التي يستطيع الحاسوب الكمومي تنفيذها فعلياً.
  4. اختيارياً تطبيق تقنيات تخفيف الأخطاء وكبتها لتقليل تأثيرات الضوضاء.

في Qiskit، يتم ذلك تلقائياً بواسطة Transpiler. بمجرد اختيار الـ Backend، يقوم Transpiler بكل العمل لجعل دائرتك جاهزة للتنفيذ، لذا لا يتعين عليك ضبط البوابات أو إسنادات الـ Qubit يدوياً. يوفر Transpiler أيضاً مستويات تحسين مختلفة يمكنها المساعدة في تقليل الأخطاء عند الحاجة. يُنجز التحسين في مراحل تُسمى «المرورات». لذا سيتولى هذا التحسين pass_manager في الكود أدناه. لمعرفة المزيد حول الأخطاء وتخفيفها، اطلع على دورة الحوسبة الكمومية في الممارسة لأوليفيا لينز.

# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService

## Load the Qiskit Runtime service
# QiskitRuntimeService.save_account(
# channel="ibm_quantum_platform",
# token="YOUR_TOKEN_HERE",
# overwrite=True,
# set_as_default=True,
# )
# service = QiskitRuntimeService(channel="ibm_quantum_platform")

# Or load saved credentials
service = QiskitRuntimeService()

# Use the least busy backend, or uncomment the loading of a specific backend like "ibm_brisbane".
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
# backend = service.backend("ibm_brisbane")
print(backend.name)
ibm_fez
# Transpile the circuit and optimize for running on the quantum computer selected
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)

qc_isa.draw("mpl")

Output of the previous code cell

التنفيذ

الآن نحن مستعدون للتنفيذ! سنحمّل Sampler ثم نرسل المهمة إلى الـ Backend.

# Load the Runtime primitive and session
from qiskit_ibm_runtime import SamplerV2 as Sampler

sampler = Sampler(mode=backend)

أو، إذا كنت تستخدم محاكياً، يمكنك إلغاء التعليق وتشغيل هذه الخلية بدلاً من ذلك:

## Load the backend sampler
# from qiskit.primitives import BackendSamplerV2

## Load the Aer simulator and generate a noise model based on the currently-selected backend.
# from qiskit_aer import AerSimulator
# from qiskit_aer.noise import NoiseModel

# noise_model = NoiseModel.from_backend(backend)

## Define a simulator using Aer, and use it in Sampler.
# backend_sim = AerSimulator(noise_model=noise_model)
# sampler_sim = BackendSamplerV2(backend=backend_sim)

## Alternatively, load a fake backend with generic properties and define a simulator.
## backend_gen = GenericBackendV2(num_qubits=18)
## sampler_gen = BackendSamplerV2(backend=backend_gen)
job = sampler.run([qc_isa], shots=100)
# job = sampler_sim.run([qc_isa]) # uncomment if you want to run on a simulator
res = job.result()
counts = res[0].data.meas.get_counts()

المعالجة اللاحقة

from qiskit.visualization import plot_histogram

print("counts = ", counts)
plot_histogram(counts)
counts =  {'10': 49, '01': 50, '11': 1}

Output of the previous code cell

نرى أن غالبية الأعداد إما في 01 أو 10، مما يعني أنه حين قيست إحدى الـ Qubits على أنها 0، كانت الأخرى 1، والعكس صحيح. هذا متسق مع حالة Bell Ψ\vert \Psi^- \rangle التي هيّأناها.

التجربة 2: استخدام Estimator لقياس الطاقة

الآن بعد أن رأينا كيف نأخذ عيّنة من حالة كمومية، لنستخدم Estimator لحساب طاقة حالة Bell لدينا Ψ=12(0110)\vert \Psi^- \rangle = \frac{1}{\sqrt{2}}(\vert 01 \rangle - \vert 10 \rangle).

التعيين

كتذكير، تتحدد طاقة النظام بالتفاعل بين الغزول (JJ) والمجال المغناطيسي الخارجي (hxh_x) كما يُعبّر عنه الهاميلتوني:

H=JZ1Z0+hx(X1+X0)H = J Z_1 Z_0 + h_x (X_1 + X_0)

يخبرنا كل حد في الهاميلتوني بكيفية مساهمة تركيبة معينة من الغزول في الطاقة. في Qiskit، يمكننا تمثيل هذه الحدود كمؤثرات باولي، وهي مجرد تسميات لإجراءات بسيطة على الـ Qubits:

  • Z1Z0Z_1 Z_0 تعمل بـ ZZ على كلا الـ Qubitين.
  • X0X_0 تعمل بـ XX على الـ Qubit 0.
  • X1X_1 تعمل بـ XX على الـ Qubit 1.

SparsePauliOp في Qiskit طريقة لتخزين قائمة من مؤثرات باولي هذه مع معاملاتها العددية. هذه المؤثرات هي العناصر القابلة للرصد التي نريد من الحاسوب الكمومي قياسها — الكميات التي تخبرنا عن النظام. باستخدام Estimator، يمكننا حساب القيمة المتوسطة لكل عنصر قابل للرصد على حالتنا وتجميعها وفق المعاملات في الهاميلتوني للحصول على إجمالي الطاقة.

# Import Qiskit primitives
from qiskit.quantum_info import SparsePauliOp

# Parameters
J = 1.0 # antiferromagnetic coupling (J<0)
hx = -0.5 # transverse field strength

# 1. Define the Hamiltonian H = J Z1 Z2 + hx (X1 + X2)
obs = SparsePauliOp.from_list([("ZZ", J), ("XI", hx), ("IX", hx)])

# Make state
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.x(1)
qc.z(0)
<qiskit.circuit.instructionset.InstructionSet at 0x1387ed630>

لاحظ أننا حذفنا سطر qc.measure_all() من كودنا. ذلك لأننا مع Estimator لا نحتاج إلى تحديد أين نقيس في الدائرة. سنخبره فقط بالعناصر القابلة للرصد التي نريد تقديرها، وسيتولى Qiskit القياسات خلف الكواليس.

التحسين

تسير خطوة التحسين كما سبق، مع إضافة التأكد من أن عناصرنا القابلة للرصد مكتوبة أيضاً بطريقة يستطيع الحاسوب الكمومي فهمها.

# Transpile the circuit and optimize for running on the quantum computer selected
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)

qc_isa.draw("mpl")

Output of the previous code cell

التنفيذ

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

# Load the Runtime primitive and session
from qiskit_ibm_runtime import EstimatorV2 as Estimator

estimator = Estimator(mode=backend)
# Load the backend sampler

# noise_model = NoiseModel.from_backend(backend)

# Use Aer simulator in Estimator
# estimator_sim = BackendEstimatorV2(backend=backend_sim)

# Alternatively, load a fake backend with generic properties and define a simulator.
# backend_gen = GenericBackendV2(num_qubits=18)
# estimator_gen = BackendEstimatorV2(backend=backend_gen)
pubs = [(qc_isa, obs_isa)]
job = estimator.run([[qc_isa, obs_isa]])
res = job.result()

# Uncomment lines below to run the job on the Aer simulator with noise model from real backend
# job = estimator_sim.run([[qc_isa,obs_isa]])
# res=job.result()

المعالجة اللاحقة

أخيراً، في خطوة المعالجة اللاحقة، نطبع ببساطة الطاقة التي حسبها Estimator خلف الكواليس.

print(res[0].data.evs)
-0.9934112021453058

هذه هي طاقة حالتنا!

الخاتمة

في هذا الدرس، تعلّمنا كيفية تهيئة حالة كمومية بسيطة ثنائية الـ Qubit تُمثّل غزلَين متفاعلَين. رأينا كيف نستخدم Sampler لرصد توزيع نتائج القياس وكيف نستخدم Estimator لحساب طاقة الحالة وفق الهاميلتوني. في الطريق، رأينا كيف يُرمّز الهاميلتوني التفاعلات بين الغزول وتأثيرات مجال خارجي، وكيف يمكن أن تكون للحالات المختلفة طاقات مختلفة.

التوسع إلى غزول كثيرة

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

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

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

هدف التعلم

عد إلى بداية التجربة 2 وجرّبها مجدداً بحالة تراكب مختلفة. هل يمكنك إيجاد حالة بطاقة أدنى حتى من التي استخدمناها؟

This translation based on the English version of 7 مايو 2026