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

حلّال القيمة الذاتية الكمّي التغايري (VQE)

لهذه الوحدة، يحتاج الطلاب إلى بيئة Python تعمل بشكل صحيح، مع أحدث إصدارات الحزم التالية مثبّتة:

  • qiskit
  • qiskit_ibm_runtime
  • qiskit-aer
  • qiskit.visualization
  • numpy
  • pylatexenc

لإعداد هذه الحزم وتثبيتها، راجع دليل تثبيت Qiskit. لتشغيل المهام على حواسيب كمّية حقيقية، يحتاج الطلاب إلى إعداد حساب IBM Cloud باتباع الخطوات الواردة في دليل إعداد حساب IBM Cloud.

تم اختبار هذه الوحدة واستخدمت ما يقارب 8 دقائق من وقت وحدة معالجة الكم (QPU). هذا تقدير تقريبي، وقد يختلف الاستخدام الفعلي.

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-ibm-runtime scipy
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'

مقدمة

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

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

في الأقسام التالية، سنستكشف عملية التكوّن الجزيئي هذه مع التركيز على جزيء H2H_2. سنستخدم حاسوباً كمّياً حقيقياً مقروناً بتقنيات التحسين الكلاسيكي لإيجاد طاقة هذه العملية البسيطة والأساسية في آنٍ معاً. سيقدم هذا التجريب عرضاً عملياً لكيفية تطبيق الحوسبة الكمّية على حل مشكلات الكيمياء الحسابية، مع إلقاء الضوء على دور طاقة الإلكترونات.

VQE - خوارزمية كمّية تغايرية لمسائل القيمة الذاتية

تقنيات التقريب في الكيمياء - المبدأ التغايري ومجموعة الأساس

لا تقتصر إسهامات إيرفين شرودنغر في ميكانيكا الكم على تقديم نموذج إلكتروني جديد؛ فقد أسّس في جوهره ميكانيكا الموجات بتطويره معادلة شرودنغر الزمنية الشهيرة:

iddtψ=H^ψi\hbar \frac{d}{dt}|\psi\rangle = \hat{H}|\psi\rangle

هنا، H^\hat{H} هو عامل هاملتون الذي يمثّل الطاقة الكلية للنظام، وψ|\psi\rangle هي دالة الموجة التي تحمل كل المعلومات عن الحالة الكمّية للنظام. (ملاحظة: ddt\frac{d}{dt} هو المشتق الكلي بالنسبة للزمن، ولا نضمّن هنا بصريح العبارة قيمة القيمة الذاتية للطاقة EE.)

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

H^ψ=Eψ\hat{H}|\psi\rangle = E|\psi\rangle

في هذه الصيغة، تمثّل EE قيمة القيمة الذاتية للطاقة المقابلة للحالة الكمّية ψ|\psi\rangle. يتضمن هاملتون مساهمات طاقوية متنوعة، كالطاقة الحركية للإلكترونات والنوى، والقوى الجاذبة بين الإلكترونات والنوى، والقوى الطاردة بين الإلكترونات.

يتيح لنا حل معادلة القيمة الذاتية للطاقة حساب مستويات الطاقة المكمّمة للأنظمة الذرية والجزيئية. إلا أن حلّها بدقة تامة أمر عسير بالنسبة للجزيئات، لأن دالة الموجة Ψ\Psi التي تصف التوزيع المكاني للإلكترونات معقدة وعالية الأبعاد.

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

  1. المبدأ التغايري

    يقرّب هذا الأسلوب دالة الموجة ويضبطها للاقتراب قدر الإمكان من الطاقة المستهدفة، وهي عادةً طاقة الحالة الأساسية للنظام. الفكرة المحورية وراء المبدأ التغايري بسيطة:

    • إذا خمّنا دالة موجة Ψtrial\Psi_\text{trial} (دالة "تجريبية")، فإن الطاقة المحسوبة منها ستكون دائماً مساوية أو أعلى من طاقة الحالة الأساسية (E0E_0) للنظام. Eapprox=ΨtrialH^ΨtrialΨtrialΨtrialE0E_\text{approx} = \frac{\langle \Psi_\text{trial}|\hat{H}|\Psi_\text{trial}\rangle}{\langle \Psi_\text{trial}|\Psi_\text{trial}\rangle} \geq E_0
    • بضبط المعاملات θ\theta في الدالة التجريبية، Ψtrial(θ)|\Psi_\text{trial}(\theta)\rangle، يمكننا الحصول على تقريب أفضل فأفضل لطاقة الحالة الأساسية.
    • تعتمد دقته بشكل كبير على اختيار دالة الموجة التجريبية Ψtrial\Psi_\text{trial}. فالدالة التجريبية المختارة بعشوائية قد تعطي تقديراً للطاقة بعيداً عن الدقة.
  2. تقريب مجموعة الأساس

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

    كثيراً ما تستلهم دوال الأساس هذه من الحلول التحليلية لأنظمة بسيطة كذرة الهيدروجين، آخذةً أشكالاً كدوال غاوس أو دوال نوع سلاتر، وإن كانت لا تزال تقريبات. وعوضاً عن العمل مع المدارات الجزيئية الكاملة "الدقيقة" نظرياً لكنها غير قابلة للحل عملياً، نعبّر عنها بوصفها تركيبة خطية (مجموعاً بمعاملات) من دوال الأساس هذه. يُعرف هذا الأسلوب بنهج التركيبة الخطية للمدارات الذرية (LCAO) حين تشبه دوال الأساس المدارات الذرية. بتحسين المعاملات في هذه التركيبة الخطية، يمكننا إيجاد أفضل دالة موجة تقريبية وطاقة ممكنتين ضمن حدود مجموعة الأساس المختارة.

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

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

تحقق من فهمك

تأمّل دالة الموجة التجريبية Ψtrial(α,x)=Aeαx2\Psi_\text{trial}(\alpha,x) = Ae^{- \alpha x^2} حيث AA ثابت تسوية وα\alpha معامل قابل للضبط.

(a) سوّ دالة الموجة التجريبية بإيجاد AA بحيث

Ψtrial2dx=1\int_{-\infty}^{\infty} |\Psi_\text{trial}|^2 dx = 1.

(b) احسب القيمة المتوقعة لعامل هاملتون H^\hat{H} المعطى بـ:

H^=22md2dx2+V(x) \hat{H} = -\frac{\hbar^2}{2m} \frac{d^2}{dx^2} + V(x) حيث V(x)=12mω2x2V(x) = \frac{1}{2}m\omega^2x^2، وهو ما يقابل كمون المذبذب التوافقي البسيط.

(c) استخدم المبدأ التغايري لإيجاد α\alpha الأمثل بتصغير Eapprox(α)E_\text{approx}(\alpha)

الإجابة:

(a) لتسوية دالة الموجة التجريبية المعطاة:

Ψtrial2dx=A2e2αx2dx=1\int_{-\infty}^{\infty} |\Psi_\text{trial}|^2 dx = \int_{-\infty}^{\infty} A^2 e^{-2 \alpha x^2} dx = 1

استخدم تكامل غاوس:

eax2dx=πa, for a>0 \int_{-\infty}^{\infty} e^{-a x^2} dx = \sqrt{\frac{\pi}{a}} \text{, for } a>0

ضع a=2αa = 2\alpha فتحصل على: A2πa=1A^2\sqrt{\frac{\pi}{a}} = 1 A=(2απ)1/4\therefore A = (\frac{2\alpha}{\pi})^{1/4}

(b) هاملتون المذبذب التوافقي هو:

H^=22md2dx2+12mω2x2\hat{H} = -\frac{\hbar^2}{2m} \frac{d^2}{dx^2} + \frac{1}{2} m \omega^2 x^2

  • القيمة المتوقعة للطاقة الحركية

T=22mΨtriald2dx2Ψtrialdx\langle T \rangle = -\frac{\hbar^2}{2m} \int_{-\infty}^{\infty} \Psi_\text{trial}^* \frac{d^2}{dx^2} \Psi_\text{trial} dx

بأخذ المشتق الثاني:

ddxΨtrial=2αxAeαx2\frac{d}{dx} \Psi_\text{trial} = -2\alpha x A e^{-\alpha x^2}d2dx2Ψtrial=Aeαx2(4α2x22α)\frac{d^2}{dx^2} \Psi_\text{trial} = A e^{-\alpha x^2} (4\alpha^2 x^2 - 2\alpha)

وبذلك:

T=22mA2e2αx2(4α2x22α)dxT = -\frac{\hbar^2}{2m} \int_{-\infty}^{\infty} A^2 e^{-2\alpha x^2} (4\alpha^2 x^2 - 2\alpha) dx

باستخدام نتائج تكامل غاوس القياسية:

T=2α2m\langle T \rangle = \frac{\hbar^2 \alpha}{2m}
  • القيمة المتوقعة للطاقة الكامنة
V=12mω2x2Ψtrial2dx\langle V \rangle = \frac{1}{2} m \omega^2 \int_{-\infty}^{\infty} x^2 |\Psi_\text{trial}|^2 dx

باستخدام:

x2eax2dx=π2a3/2\int_{-\infty}^{\infty} x^2 e^{-a x^2} dx = \frac{\sqrt{\pi}}{2a^{3/2}}

نحصل على:

V=mω24α\langle V \rangle = \frac{m \omega^2}{4\alpha}
  • القيمة المتوقعة للطاقة الكلية
Eapprox(α)=2α2m+mω24α\therefore E_\text{approx}(\alpha) = \frac{\hbar^2 \alpha}{2m} + \frac{m \omega^2}{4\alpha}

(c) تحسين α\alpha للحصول على الطاقة الدنيا

الاشتقاق:

ddα(2α2m+mω24α)=0\frac{d}{d\alpha} \left( \frac{\hbar^2 \alpha}{2m} + \frac{m \omega^2}{4\alpha} \right) = 0

بالحل:

22mmω24α2=0\frac{\hbar^2}{2m} - \frac{m \omega^2}{4\alpha^2} = 0αopt=mω2\alpha_\text{opt} = \frac{m\omega}{2\hbar}

بتعويض αopt\alpha_\text{opt} في EapproxE_\text{approx}:

Eapprox=ω2\therefore E_\text{approx} = \frac{\hbar \omega}{2}

وهو ما يطابق طاقة الحالة الأساسية الدقيقة للمذبذب التوافقي الكمّي.

VQE (حلّال القيمة الذاتية الكمّي التغايري)

حلّال القيمة الذاتية الكمّي التغايري (VQE) هو الأسلوب الرئيسي الذي سنستخدمه لاستكشاف عملية H+H=H2H+H = H_2، وسنلقي هنا نظرة على ماهية VQE وآلية عمله. لكن لنتوقف أولاً ونستعرض أمراً بالغ الأهمية من خلال سؤال التحقق التالي.

تحقق من فهمك

إذا كان لدينا بالفعل هذا الكم من الاستراتيجيات لمسائل الكيمياء، فلماذا نحتاج إلى حاسوب كمّي؟ وما الغرض من استخدام الحواسيب الكمّية والكلاسيكية معاً؟

الإجابة:

تملك الحوسبة الكمّية فرصة لإحداث ثورة في الكيمياء من خلال معالجة المسائل التي تعجز الحواسيب الكلاسيكية عنها بسبب التمدد الأسي لحالات الكم. أشار ريتشارد فاينمان بعبارته الشهيرة إلى أن محاكاة الطبيعة تستلزم أن تكون الحسابات بدورها كمّية [مرجع 1].

فمثلاً، محاكاة مادة الكافيين بأبسط مجموعة أساس (STO-3G) تتطلب 104810^{48} بت، وهو عدد أكبر بكثير من إجمالي عدد النجوم في الكون المرئي (102410^{24}) [مرجع 2]. أما الحاسوب الكمّي فبإمكانه وصف المدارات الإلكترونية للكافيين بـ160 كيوبت فحسب.

تعالج الحواسيب الكمّية التفاعلات الكمّية بطبيعتها مستخدمةً التراكب والتشابك الكمّي، مما يوفر سبيلاً واعداً لتمكين محاكاة جزيئية دقيقة. فضلاً عن ذلك، يمكننا الجمع بين مزايا الحواسيب الكمّية (محاكاة الإلكترونات) والحواسيب الكلاسيكية (المعالجة المسبقة واللاحقة للبيانات، وإدارة عمليات الخوارزميات، والتحسين، وغير ذلك). ومن المتوقع أن يعزز هذا التكامل اكتشاف المواد، وتصميم الأدوية، والتنبؤ بالتفاعلات، مما يقلص التجارب المكلفة بالمحاولة والخطأ. [مرجع 3][مرجع 4]

إذا أردت معرفة لماذا تُحتاج الحواسيب الكمّية لمسائل الكيمياء ولماذا نستخدم الحوسبة الكمّية والكلاسيكية معاً، فاطّلع على المقالات التالية:

لنعد الآن إلى VQE.

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

VQE workflow

(الجزء الكمّي) المقياس: هاملتون الجزيء (طاقة الجزيء)

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

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

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

في هذه الوحدة، سنزودك بهاملتونات (أحادية الكيوبت) مناسبة لـHH وH2H_2 كي نتمكن من التركيز على استخدام الحاسوب الكمّي. هذه الهاملتونات أحادية الكيوبت مُعدّة باستخدام مجموعة الأساس STO-6G ورسم الخريطة Jordan-Wigner، وهو أبسط رسم خريطة بأوضح تفسير فيزيائي، إذ يربط إشغال دوران-مدار واحد بإشغال كيوبت واحد. كما استخدمنا تقنية تقليص الكيوبتات باستغلال تماثل الهاملتون، التي تستخدم الأنماط في سلوك إشغالات الدوران لتقليل عدد الكيوبتات. لجزيء H2H_2، نفترض أن المسافة بين ذرتَي الهيدروجين هي 0.735 A˚\mathring A.

(الجزء الكمّي) الـ Ansatz: دالة الموجة التجريبية (كيفية بناء حالة كمّية بسيطة بدائرة كمّية)

في VQE، يتكوّن الـ ansatz (الجمع: ansätze) من مكوّنين رئيسيين. الأول هو تحضير الحالة الابتدائية، الذي يُهيئ حالة الكيوبت بتطبيق بوابات كمّية بدون معاملات تغايرية. أما المكوّن الثاني فهو الدائرة الكمّية ذات المعاملات، وهي دائرة كمّية خاصة بمعاملات قابلة للضبط، شبيهة بأقراص ضبط الراديو. ستُستخدم هذه المعاملات في الجزء الأخير — المحسّن الكلاسيكي — لمساعدتنا على الوصول إلى أفضل حالة أساسية ممكنة.

في قسم المبدأ التغايري، تعلمنا أن جودة الحالة التجريبية تؤثر على جودة نتائج الخوارزمية التغايرية. هذا يعني أن اختيار ansatz جيد أمر مهم في VQE. مرة أخرى، هذا موضوع غني ومعقد. لن نتناول هنا أنواع الـ ansatz المختلفة أو أصولها. إن كنت مهتماً بمعرفة المزيد عن الدوائر الكمّية ذات المعاملات والـ ansatz، يمكنك استكشاف درس الـ Ansatz والصيغة التغايرية من دورة تصميم الخوارزميات التغايرية، الذي يقدم شروحات وأمثلة تفصيلية عن ansätze.

بما أننا سنستخدم هاملتون أحادي الكيوبت في هذه الوحدة، نحتاج إلى دائرة كمّية أحادية الكيوبت ذات معاملات بوصفها ansatz. سنستعرض في القسم التالي ثلاثة أنواع من ansätze أحادية الكيوبت، ونقارن بينها ونناقش الاعتبارات الرئيسية في اختيار الـ ansatz.

(الجزء الكلاسيكي) المحسّن: الضبط الدقيق للدائرة الكمّية

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

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

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

الآن أنت مستعد لإجراء حساب VQE. لذا، جرّب سؤال التحقق أدناه الذي يلخص العملية الكاملة.

تحقق من فهمك

املأ الفراغات بالمصطلحات الصحيحة لإكمال ملخص عملية VQE.

VQE هو خوارزمية كمّية تغايرية تجمع بين قدرة (1) ________ والحوسبة الكلاسيكية، وتُستخدم لإيجاد (2) __________ لجزيء ما. تبدأ العملية بتعريف (3) __________، الذي يمثّل الطاقة الكلية للنظام ويعمل بوصفه مقياساً في القياسات الكمّية. بعدها نُعدّ (4) __________، وهو دائرة كمّية بمعاملات قابلة للضبط تمثّل دالة الموجة التجريبية للجزيء. تُحسَّن هذه المعاملات باستخدام (5) __________، وهو خوارزمية كلاسيكية تضبط المعاملات بصورة تكرارية لتصغير الطاقة المقاسة. في النقاش أعلاه استخدمنا محسّن (6) __________، الذي يُعدّل معاملات الـ ansatz دون الحاجة إلى حسابات تفاضلية. تستمر العملية حتى نصل إلى (7) __________، أي إيجاد أدنى طاقة ممكنة للجزيء.

بنك الكلمات:

  • classical optimizer (المحسّن الكلاسيكي)
  • ground state energy (طاقة الحالة الأساسية)
  • hardware-efficient (كفء للعتاد)
  • ansatz
  • molecular Hamiltonian (هاملتون الجزيء)
  • COBYLA
  • quantum computing (الحوسبة الكمّية)
  • convergence (التقارب)

الإجابة:

1 → quantum computing (الحوسبة الكمّية)

2 → ground state energy (طاقة الحالة الأساسية)

3 → molecular Hamiltonian (هاملتون الجزيء)

4 → ansatz

5 → classical optimizer (المحسّن الكلاسيكي)

6 → COBYLA

7 → convergence (التقارب)

احسب طاقة الحالة الأساسية لذرة الهيدروجين باستخدام VQE

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

  • الخطوة 1: تحويل المدخلات الكلاسيكية إلى مسألة كمومية
  • الخطوة 2: تحسين المسألة لتناسب التنفيذ الكمومي
  • الخطوة 3: التنفيذ باستخدام أوليّات Qiskit Runtime
  • الخطوة 4: المعالجة اللاحقة والتحليل الكلاسيكي

نمط Qiskit

سنتبع هذه الخطوات بشكل عام.

لنبدأ بتحميل بعض الحزم الضرورية، بما فيها أوليّات Qiskit Runtime. كما سنختار أقل جهاز حوسبة كمومية انشغالاً متاح لنا.

يوجد أدناه كود لحفظ بيانات اعتمادك عند الاستخدام الأول. تأكد من حذف هذه المعلومات من الدفتر بعد حفظها في بيئتك، حتى لا تُشارَك بيانات اعتمادك بشكل غير مقصود عند مشاركة الدفتر. راجع إعداد حسابك في IBM Cloud وتهيئة الخدمة في بيئة غير موثوقة للحصول على مزيد من التوجيهات.

# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService

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

# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform', instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')

# 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_brisbane

الخلية التالية ستتيح لك التبديل بين استخدام المحاكي أو العتاد الفعلي على مدار الدفتر. نوصي بتشغيلها الآن:

# 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

# Alternatively, load a fake backend with generic properties and define a simulator.

noise_model = NoiseModel.from_backend(backend)

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

الخطوة 1: تحويل المسألة إلى دوائر كمومية ومؤثرات

نبدأ حساب VQE بتعريف هاملتونيان جزيئة الهيدروجين (H2H_2) عند مسافة ربط محددة. يمثّل هذا الهاملتونيان الطاقة الكلية للنظام من حيث مؤثرات الكيوبت، وقد جرى اشتقاقه وتحويله من النظام الجزيئي باتباع إجراء قياسي: 1) استخدام مجموعة الأساس STO-6G (مجموعة محددة من الدوال الرياضية تُستخدم لتقريب المدارات الإلكترونية)، 2) تطبيق تحويل جوردان-ويغنر (تقنية لترجمة المؤثرات الفيرميونية التي تصف الإلكترونات إلى مؤثرات كيوبت)، 3) إجراء تقليل الكيوبت باستخدام تماثلات الهاملتونيان لتبسيط المسألة.

كما أوضحنا سابقاً، تعتمد طاقات الحالة الأساسية المحسوبة اعتماداً كبيراً على اختيار مجموعة الأساس والشكل الهندسي للجزيء (كمسافة الربط). لهذا التهيئة المحددة وبعد هذه التحويلات، يكون الهاملتونيان الكيوبتي الناتج بسيطاً:

H^=0.2355I+0.2355Z\hat{H} = -0.2355 I + 0.2355 Z

هنا، يمثّل II مؤثر الهوية ويمثّل ZZ مؤثر باولي-Z، ويعملان على كيوبت واحد. تُشتق المعاملات من التكاملات المحسوبة باستخدام مجموعة الأساس STO-6G عند مسافة الربط هذه مع التحويل المناسب.

بعد تعريف هذا الهاملتونيان، يمكننا الآن استخدام VQE لحساب طاقة حالته الأساسية. من المفيد مقارنة طاقة الحالة الأساسية المحسوبة لدينا بالقيم المتوقعة. لذرة هيدروجين واحدة معزولة (H)، تكون طاقة الحالة الأساسية تساوي تماماً -0.5 هارتري (في غياب التأثيرات النسبية). لنحسب طاقة الحالة الأساسية الدقيقة لهاملتونياننا الكيوبتي المحدد كما هو معرّف أعلاه ونقارنه بالقيم المعروفة ذات الصلة.

from qiskit.quantum_info import SparsePauliOp
import numpy as np

# Qubit Hamiltonian of the hydrogen atom generated by using STO-3G basis set and parity mapping
Hamiltonian = SparsePauliOp.from_list([("I", -0.2355), ("Z", 0.2355)])

# exact ground state energy of Hamiltonian

A = np.array(Hamiltonian)
eigenvalues, eigenvectors = np.linalg.eig(A)
print(
"The exact ground state energy of the Hamiltonian is ",
min(eigenvalues).real,
"hartree",
)
h = min(eigenvalues.real)
The exact ground state energy of the Hamiltonian is  -0.471 hartree

بعد ذلك، نحتاج إلى دائرة كمومية ذات معاملات، أي أنساتز، لتهيئة دالة موجة تجريبية Ψtrial\Psi_\text{trial} للحالة الأساسية. الهدف هو إيجاد المعاملات θ\theta التي تقلّل قيمة توقع الطاقة ψ(θ)H^ψ(θ)\langle\psi(\theta)|\hat{H}|\psi(\theta)\rangle. يُعدّ اختيار الأنساتز أمراً بالغ الأهمية لأنه يحدد مجموعة الحالات الكمومية الممكنة التي يمكن لدائرتنا إعدادها. الأنساتز "الجيد" هو الذي يكون مرناً بما يكفي لتمثيل حالة قريبة جداً من الحالة الأساسية الحقيقية للهاملتونيان الذي ندرسه، لكن ليس بالغ التعقيد بحيث يتطلب معاملات كثيرة أو دائرة عميقة جداً لأجهزة الحوسبة الكمومية الحالية.

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

سنستخدم ثلاثة أنساتزات مستندة إلى مجموعات مختلفة من بوابات الدوران أحادية الكيوبت:

  • أنساتز بوابة دوران حول محور واحد: يستخدم هذا الأنساتز الدورانات حول محور واحد فقط (Rx(θ)R_x(\theta)). على كرة بلوخ، يقابل هذا التحرك على طول دائرة محددة فقط. وهو الأقل مرونة ويغطي مجموعة محدودة من الحالات.
  • أنساتزان ببوابتَي دوران حول محورَين: يجمع هذان الأنساتزان الدورانات حول محورين مختلفين (Rx(θ1)Rz(θ2)R_x(\theta_1) R_z(\theta_2) و Rx(θ1)Rz(θ2)Rx(θ3)R_x(\theta_1) R_z(\theta_2) R_x(\theta_3)). يتيح هذا الوصول إلى جزء أكبر من كرة بلوخ مقارنةً بالدوران حول محور واحد.

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

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.quantum_info import Statevector, DensityMatrix, Pauli

theta = Parameter("θ")
phi = Parameter("φ")
lam = Parameter("λ")

ansatz1 = QuantumCircuit(1)
ansatz1.rx(theta, 0)

ansatz2 = QuantumCircuit(1)
ansatz2.rx(theta, 0)
ansatz2.rz(phi, 0)

ansatz3 = QuantumCircuit(1)
ansatz3.rx(theta, 0)
ansatz3.rz(phi, 0)
ansatz3.rx(lam, 0)
<qiskit.circuit.instructionset.InstructionSet at 0x1059def80>

الآن، لنولّد 5000 رقم عشوائي لكل معامل ونرسم توزيع الحالات الكمومية العشوائية التي تولّدها الأنساتزات الثلاثة بهذه المعاملات العشوائية. يمكنك التفكير في هذه المعاملات كدورانات حول محاور مختلفة على سطح كروي. لرؤية توزيع الحالة الكمومية، سنستخدم كرة بلوخ، وهي كرة ثلاثية الأبعاد تُظهر حالة كيوبت واحد. أي نقطة على الكرة تمثل حالة ممكنة للكيوبت، حيث يشبه القطبان الشمالي والجنوبي الحالتين الكلاسيكيتين "0" و"1"، لكن يمكن للكيوبت أن يكون في أي مكان بينهما، مما يُظهر خصائص كمومية خاصة كالتراكب. أولاً، جهّز الدوال اللازمة لرسم كرة بلوخ ثلاثية الأبعاد وأعدّ 5000 معامل عشوائي.

import matplotlib.pyplot as plt

def plot_bloch(bloch_vectors):
# Extract X, Y, Z coordinates for 3D projection
X_coords = bloch_vectors[:, 0]
Z_coords = bloch_vectors[:, 2]

# Compute Y coordinates from X and Z to approximate the full Bloch sphere projection
Y_coords = bloch_vectors[:, 1]

# Create 3D plot
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, projection="3d")
ax.scatter(X_coords, Y_coords, Z_coords, color="blue", alpha=0.6)

# Labels and title
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.set_title("Parameterized 1-Qubit Circuit on 3D Bloch Sphere")

# Set axis limits and make them equal
ax.set_xlim([-1, 1])
ax.set_ylim([-1, 1])
ax.set_zlim([-1, 1])

# Ensure equal aspect ratio for all axes
ax.set_box_aspect([1, 1, 1]) # Equal scaling for x, y, z axes

# Show grid
ax.grid(True)

plt.show()

num_samples = 5000 # Number of random states
theta_vals = np.random.uniform(0, 2 * np.pi, num_samples)
phi_vals = np.random.uniform(0, 2 * np.pi, num_samples)
lam_vals = np.random.uniform(0, 2 * np.pi, num_samples)

لنرَ كيف يعمل أنساتزنا الأول.

# List to store Bloch Sphere XZ coordinates
bloch_vectors = []

# Generate quantum states and extract Bloch vectors
for i in range(num_samples):
# Create a circuit and bind parameters
qc = ansatz1
bound_qc = qc.assign_parameters({theta: theta_vals[i]}) # , lam: lam_vals[i]})
state = Statevector.from_instruction(bound_qc)
rho = DensityMatrix(state)

X = rho.expectation_value(Pauli("X")).real
Y = rho.expectation_value(Pauli("Y")).real
Z = rho.expectation_value(Pauli("Z")).real
bloch_vectors.append([X, Y, Z]) # Store X, Z components

# Convert to a numpy array for plotting
bloch_vectors = np.array(bloch_vectors)

plot_bloch(bloch_vectors)

ناتج خلية الكود السابقة

يمكننا أن نرى أن أنساتزنا الأول يُعيد حالات كمومية موزّعة على شكل حلقة على كرة بلوخ. وهذا منطقي، لأننا أعطينا الأنساتز معاملاً دورانياً واحداً فقط، فلا يمكنه إذن إلا إنتاج حالات تُشكّل دورانات حول محور واحد. الانطلاق من النقطة (0,0,1)(0,0,1) والدوران حول محور واحد سينتج دائماً حلقة. ثم لنتحقق من أنساتزنا الثاني الذي يحتوي على بوابتَي دوران متعامدتَين - Rx و Rz.

bloch_vectors = []

# Generate quantum states and extract Bloch vectors
for i in range(num_samples):
# Create circuit and bind parameters
qc = ansatz2
bound_qc = qc.assign_parameters(
{theta: theta_vals[i], phi: phi_vals[i]}
) # , lam: lam_vals[i]})
state = Statevector.from_instruction(bound_qc)
rho = DensityMatrix(state)

X = rho.expectation_value(Pauli("X")).real
Y = rho.expectation_value(Pauli("Y")).real
Z = rho.expectation_value(Pauli("Z")).real
bloch_vectors.append([X, Y, Z]) # Store X, Z components

# Convert to numpy array for plotting
bloch_vectors = np.array(bloch_vectors)

plot_bloch(bloch_vectors)

ناتج خلية الكود السابقة

هنا يمكننا أن نرى أن أنساتزنا الثاني يغطي جزءاً أكبر من كرة بلوخ - لكن لاحظ أن النقاط تتمركز أكثر عند القطبين وتنتشر أكثر عند خط الاستواء. حان الآن وقت التحقق من أنساتزنا الأخير.

bloch_vectors = []

# Generate quantum states and extract Bloch vectors
for i in range(num_samples):
# Create circuit and bind parameters
qc = ansatz3
bound_qc = qc.assign_parameters(
{theta: theta_vals[i], phi: phi_vals[i], lam: lam_vals[i]}
)
state = Statevector.from_instruction(bound_qc)
rho = DensityMatrix(state)

X = rho.expectation_value(Pauli("X")).real
Y = rho.expectation_value(Pauli("Y")).real
Z = rho.expectation_value(Pauli("Z")).real
bloch_vectors.append([X, Y, Z]) # Store X, Z components

# Convert to numpy array for plotting
bloch_vectors = np.array(bloch_vectors)

plot_bloch(bloch_vectors)

ناتج خلية الكود السابقة

هنا يمكنك رؤية الحالات الكمومية الأكثر انتظاماً في التوزيع التي يولّدها أنساتزنا الأخير.

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

الآن بعد أن اخترنا أنساتزنا، لنرسم الدائرة.

# Pre-defined ansatz circuit and operator class for Hamiltonian

ansatz = ansatz3

num_params = ansatz.num_parameters
print("This circuit has ", num_params, "parameters")

ansatz.draw("mpl", style="iqp")
This circuit has  3 parameters

ناتج خلية الكود السابقة

الخطوة 2: التحسين لعتاد الهدف

عند تشغيل حساب على جهاز حوسبة كمومية حقيقي، لا نهتم فقط بمنطق الدائرة الكمومية. بل نهتم أيضاً بأشياء مثل العمليات التي يمكن لذلك الجهاز الكمومي تنفيذها، وأين على الجهاز تقع الكيوبتات التي نستخدمها - هل هي متجاورة أم متباعدة؟ لذلك، الخطوة التالية هي إعادة كتابة دائرتنا باستخدام بوابات طبيعية لجهاز الحوسبة الكمومية الذي سنستخدمه، مع مراعاة تخطيط الكيوبتات. يمكن تحقيق ذلك عبر الترجمة (transpilation) - بعد هذه العملية، يمكنك رؤية أنساتزنا البسيط وقد تحوّل إلى مجموعة مختلفة من البوابات، وستُعيَّن كيوبتاتنا المجردة إلى كيوبتات فيزيائية على جهاز كمومي حقيقي.

from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

config = backend.configuration()

print("Backend: {config.backend_name}")
print("Native gates: ", config.supported_instructions, ",")

target = backend.target

pm = generate_preset_pass_manager(target=target, optimization_level=3)

ansatz_isa = pm.run(ansatz)

ansatz_isa.draw(output="mpl", idle_wires=False, style="iqp")
Backend: {config.backend_name}
Native gates: ['ecr', 'id', 'delay', 'measure', 'reset', 'rz', 'sx', 'x'] ,

ناتج خلية الكود السابقة

يمكنك ملاحظة أن بوابتَي rx, rz في أنساتزنا تحوّلتا إلى سلسلة من بوابات rz, sx، وهي البوابات الأصيلة لواجهتنا الخلفية. كذلك يمكنك رؤية أن q0 لدينا أصبح مُعيَّناً إلى الكيوبت الفيزيائي الخامس. نحتاج أيضاً إلى تحويل هاملتونياننا وفقاً لهذه التغييرات، كما في الكود التالي:

Hamiltonian_isa = Hamiltonian.apply_layout(layout=ansatz_isa.layout)

الخطوة 3: التنفيذ على عتاد الهدف

حان الآن وقت تشغيل VQE على وحدة معالجة كمومية حقيقية. لهذا، نحتاج أولاً إلى دالة تكلفة لعملية التحسين، تحسب قيمة توقع الهاملتونيان لحالة كمومية يولّدها الأنساتز. لا تقلق! لا تحتاج إلى كتابة كل شيء بنفسك. لقد أعددنا لك دالة لذلك، وكل ما عليك فعله هو تشغيل الخلية أدناه.

def cost_func(params, ansatz, hamiltonian, estimator):
"""Return estimate of energy from estimator

Parameters:
params (ndarray): Array of ansatz parameters
ansatz (QuantumCircuit): Parameterized ansatz circuit
hamiltonian (SparsePauliOp): Operator representation of Hamiltonian
estimator (EstimatorV2): Estimator primitive instance
cost_history_dict: Dictionary for storing intermediate results

Returns:
float: Energy estimate
"""
pub = (ansatz, [hamiltonian], [params])
result = estimator.run(pubs=[pub]).result()
energy = result[0].data.evs[0]

cost_history_dict["iters"] += 1
cost_history_dict["prev_vector"] = params
cost_history_dict["cost_history"].append(energy)
print(f"Iters. done: {cost_history_dict['iters']} [Current cost: {energy}]")

return energy

أخيراً، نجهّز المعاملات الأولية لأنساتزنا وعملية تحسينه. يمكنك ببساطة استخدام أصفار أو قيم عشوائية. اخترنا المعاملات الأولية أدناه، لكن لا تتردد في تعليق أو إلغاء تعليق الأسطر في الخلية لأخذ عينة من المعاملات بشكل عشوائي وبشكل منتظم من 0 إلى 2π2\pi.

# x0 = np.random.uniform(0, 2*pi, 3)
x0 = [1, 1, 0]
# QPU Est. 2min for ibm_brisbane

from scipy.optimize import minimize
from qiskit_ibm_runtime import Batch

batch = Batch(backend=backend)

cost_history_dict = {
"prev_vector": None,
"iters": 0,
"cost_history": [],
}
estimator = Estimator(mode=batch)
estimator.options.default_shots = 10000

res = minimize(
cost_func,
x0,
args=(ansatz_isa, Hamiltonian_isa, estimator),
method="cobyla",
options={"maxiter": 10, "tol": 0.01},
)

batch.close()
Iters. done: 1 [Current cost: -0.3361517318448143]
Iters. done: 2 [Current cost: -0.4682546422099432]
Iters. done: 3 [Current cost: -0.38985802144149584]
Iters. done: 4 [Current cost: -0.38319217316749354]
Iters. done: 5 [Current cost: -0.4628720756579032]
Iters. done: 6 [Current cost: -0.4683301936226905]
Iters. done: 7 [Current cost: -0.45480498699294747]
Iters. done: 8 [Current cost: -0.4690533242050814]
Iters. done: 9 [Current cost: -0.465867415110354]
Iters. done: 10 [Current cost: -0.4606882723137227]
h_vqe = res.fun
print("The reference ground state energy is ", min(eigenvalues))
print("The computed ground state energy is ", h_vqe)
The reference ground state energy is  (-0.471+0j)
The computed ground state energy is -0.4690533242050814

تهانينا! لقد أتممت للتو أول تجربة لك في الكيمياء الكمومية بنجاح. يمكننا رؤية فارق بين طاقة الحالة الأساسية الدقيقة للهاملتونيان وطاقتنا المحسوبة، لكن لأننا استخدمنا تقنية افتراضية للتخفيف من الأخطاء (التي تصحح أخطاء القراءة)، يبقى الفارق طفيفاً. هذه بداية ممتازة!

ملاحظة: يمكنك الحصول على نتيجة أفضل بضبط مستوى تخفيف الأخطاء باستخدام resilience_level. القيمة الافتراضية هي 1، وإذا ضبطت قيمة أعلى، سيستغرق ذلك وقتاً أطول من وحدة المعالجة الكمومية لكنه قد يُعيد نتيجة أفضل.

الخطوة 4: المعالجة اللاحقة

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

fig, ax = plt.subplots()
x = np.linspace(0, 10, 10)

# Define the constant function
y_constant = np.full_like(x, h)
ax.plot(
range(cost_history_dict["iters"]), cost_history_dict["cost_history"], label="VQE"
)
ax.set_xlabel("Iterations")
ax.set_ylabel("Cost (Hartree)")
ax.plot(y_constant, label="Target")
plt.legend()
plt.draw()

ناتج خلية الكود السابقة

بدأنا بقيمة أولية جيدة إلى حد ما، لذا حصلنا على قيمة نهائية جيدة في 10 خطوات فقط. يمكنك رؤية قمم كبيرة وصغيرة، وهذه السمة النموذجية للمحسّن COBYLA - يستكشف الفضاء كأنه لا يستطيع رؤية المشهد ويضبط حجم الخطوة مع كل قياس.

اختبر فهمك

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

الجواب:

أول ما ينبغي مراعاته هو تغيير مجموعة الأسس المستخدمة في حساب هاملتونيان الجزيئات. كما ذكرنا سابقاً، طاقة الحالة الأساسية لذرة H هي -0.5 هارتري كما هو معروف جيداً، وأساس STO-6G الذي اخترناه لا يكفي لاشتقاق هذه القيمة بدقة.

اختيار نوع أساس أكثر تعقيداً يزيد من عدد الكيوبتات التي يستخدمها الهاملتونيان؛ لذلك نحتاج إلى اختيار أنساتز أكثر تعقيداً وملاءمةً لمسائل الكيمياء.

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

أخيراً، يمكن تحقيق أداء تقارب أفضل بتجربة محسّنات مختلفة.

احسب طاقة الحالة الأساسية لجزيء الهيدروجين باستخدام VQE

الآن بعد أن استعرضنا العملية الكاملة لـ VQE باستخدام ذرات HH، سنحسب طاقة الحالة الأساسية لجزيء H2H_2 بصورة أسرع.

الخطوة 1: تعيين المسألة إلى دوائر كمومية ومؤثرات

نوفر لك هنا هاميلتوني أحادي الكيوبت يستخدم قاعدة STO-6G وتحويل جوردان-وينر، مع تقليل عدد الكيوبتات بالاستفادة من تماثل الهاميلتوني. لاحظ أننا استخدمنا مسافة ذرية بين ذرتَي الهيدروجين تساوي 0.735 A˚\mathring A.

على خلاف حساب ذرة الهيدروجين المفردة (HH)، فإن حساب الحالة الأساسية لجزيء الهيدروجين (H2H_2) يستلزم أيضاً أخذ قوة التنافر بين نواتَي ذرتَي الهيدروجين في الاعتبار، إضافةً إلى الطاقة المرتبطة بالمدارات الإلكترونية. في هذه الخطوة سنعطي هذه القيمة كثابت، وسنحسبها فعلياً في مسألة التحقق. H^=1.04886I+0.79674Z+0.18122X\hat{H} = -1.04886 I + -0.79674 Z + 0.18122 X

h2_hamiltonian = SparsePauliOp.from_list(
[("I", -1.04886087), ("Z", -0.7967368), ("X", 0.18121804)]
)

# exact ground state energy of hamiltonian
nuclear_repulsion = 0.71997
A = np.array(h2_hamiltonian)
eigenvalues, eigenvectors = np.linalg.eig(A)
print("Electronic ground state energy (Hartree): ", min(eigenvalues).real)
print("Nuclear repulsion energy (Hartree): ", nuclear_repulsion)
print(
"Total ground state energy (Hartree): ", min(eigenvalues).real + nuclear_repulsion
)
h2 = min(eigenvalues).real + nuclear_repulsion
Electronic ground state energy (Hartree):  -1.8659468547627318
Nuclear repulsion energy (Hartree): 0.71997
Total ground state energy (Hartree): -1.1459768547627318

الخطوة 2: التحسين لأجهزة الهدف

بما أن عدد الكيوبتات المستخدمة في VQE السابق والهاميلتوني مماثل لعدد الكيوبتات في الواجهة الخلفية المستخدمة للتنفيذ، سنستخدم نفس الـ ansatz وصورته المُحسَّنة.

h2_hamiltonian_isa = h2_hamiltonian.apply_layout(layout=ansatz_isa.layout)

الخطوة 3: التنفيذ على أجهزة الهدف

حان الوقت الآن لإجراء الحسابات على وحدة المعالجة الكمومية الفعلية (QPU). كل شيء تقريباً مماثل، لكننا سنستخدم نقطة بداية ملائمة تتناسب مع الهاميلتوني. كذلك، في الجزء التكراري، ستُضبَط بعض إعدادات Estimator —الذي يُستخدم لحساب القيم المتوقعة للهاميلتوني من خلال الـ ansatz على وحدة QPU— بصورة مختلفة قليلاً عن الحسابات السابقة. سنناقش هذا التغيير بمزيد من التفصيل في مسألة التحقق.

x0 = [2, 0, 0]
# QPU time 4min for ibm_brisbane
batch = Batch(backend=backend)

cost_history_dict = {
"prev_vector": None,
"iters": 0,
"cost_history": [],
}
estimator = Estimator(mode=batch)
estimator.options.default_shots = 10000

res = minimize(
cost_func,
x0,
args=(ansatz_isa, h2_hamiltonian_isa, estimator),
method="cobyla",
options={"maxiter": 15},
)

batch.close()
Iters. done: 1 [Current cost: -0.710621837568328]
Iters. done: 2 [Current cost: -0.2603208441168329]
Iters. done: 3 [Current cost: -0.25548711201326424]
Iters. done: 4 [Current cost: -0.581129450619904]
Iters. done: 5 [Current cost: -1.722920997605439]
Iters. done: 6 [Current cost: -1.6633324849371915]
Iters. done: 7 [Current cost: -1.8066989598929164]
Iters. done: 8 [Current cost: -1.8051093803839542]
Iters. done: 9 [Current cost: -1.802692217571555]
Iters. done: 10 [Current cost: -1.8233585485263144]
Iters. done: 11 [Current cost: -1.6904116652617205]
Iters. done: 12 [Current cost: -1.8245120321245392]
Iters. done: 13 [Current cost: -1.6837021361383608]
Iters. done: 14 [Current cost: -1.8166632606115467]
Iters. done: 15 [Current cost: -1.863446212658907]
h2_vqe = res.fun + nuclear_repulsion
print(
"The reference ground state energy is ", min(eigenvalues).real + nuclear_repulsion
)
print("The computed ground state energy is ", h2_vqe)
The reference ground state energy is  -1.1459768547627318
The computed ground state energy is -1.143476212658907

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

الخطوة 4: ما بعد المعالجة

fig, ax = plt.subplots()
x = np.linspace(0, 5, 15)

# Define the constant function
y_constant = np.full_like(x, min(eigenvalues))
ax.plot(
range(cost_history_dict["iters"]), cost_history_dict["cost_history"], label="VQE"
)
ax.set_xlabel("Iterations")
ax.set_ylabel("Cost (Hartree)")
ax.plot(y_constant, label="Target")
plt.legend()
plt.draw()

Output of the previous code cell

تحقق من فهمك

لنحسب طاقة التنافر النووي لجزيء H2H_2، التي أدرجناها كقيمة ثابتة (0.71997 Hartree).

H2 molecule

استخدم قانون كولوم والوحدات الذرية للتأكد من الحصول على القيمة بوحدة Hartree.

الجواب:

بما أن كلتا نواتَي الهيدروجين مشحونتان بشحنة موجبة، فإنهما تتنافران بسبب القوة الكهروستاتيكية. يُوصف هذا التنافر بقانون كولوم:

Erepulsive=e24πϵ0RE_{repulsive} = \frac{e^2}{4\pi\epsilon_0R}،

حيث ee هي شحنة البروتون، وϵ0\epsilon_0 هي نفاذية الفراغ، وRR هي المسافة بين النواتين مقيسةً بالمتر أو بنصف قطر بور بوحدة الجول (J).

لحساب هذه الطاقة بوحدة هارتري، يجب تحويل المعادلة أعلاه إلى نظام الوحدات الذرية (AU). في نظام AU: e2=1e^2 = 1، و4πϵ0=14\pi\epsilon_0=1، ونصف قطر بور (a0a_0) يساوي 1 ويمثل وحدة الطول الأساسية. بهذه التبسيطات يصبح قانون كولوم:

Erepulsion=1RE_{repulsion} = \frac{1}{R}،

حيث يجب قياس RR بوحدة أنصاف أقطار بور (a0a_0).

لتحويل المسافة النووية المعطاة من A˚\r{A} إلى a0a_0، نستخدم علاقة التحويل:

1A˚=1.88973a01\r{A} = 1.88973 a_0

لذا فإن 0.735A˚0.735\r{A} تصبح 0.7351.88973=1.38895a00.735 * 1.88973 = 1.38895 a_0.

وعليه، طاقة التنافر النووي لجزيء H2H_2 المعطى هي:

Erepulsion=1R=11.38895=0.71997HartreeE_{repulsion} = \frac{1}{R} = \frac{1}{1.38895} = 0.71997 Hartree

احسب طاقة التفاعل لـ H+H=H2H + H = H_2

الآن لنستخدم ما حصلنا عليه! لقد استخدمت VQE —وهو المحلل القيمي الكمي— لحساب طاقة الحالة الأساسية لذرة HH ولجزيء H2H_2. ما تبقى هو استخدام هذه القيم المحسوبة للحصول على طاقة التفاعل لعملية H+H=H2H+H=H_2.

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

يمكن حساب طاقة التفاعل لعملية H+H=H2H+H = H_2 بالصيغة التالية:

Ereaction=EH2(EH+EH)E_{reaction} = E_{H_2} - (E_H + E_H)

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

# Theoretical values
E_H_theo = h.real
E_H2_theo = h2

# Experimental values
E_H_exp = h_vqe
E_H2_exp = h2_vqe

# Calculate reaction energies
E_reaction_theo = E_H2_theo - (2 * E_H_theo)
E_reaction_exp = E_H2_exp - (2 * E_H_exp)

# Set up the plot
fig, ax = plt.subplots(figsize=(8, 6))
ax.set_xlim(0, 3)
ax.set_ylim(-1.16, -0.93) # Adjust y-axis range to highlight differences
ax.set_xticks([])
ax.set_ylabel("Energy (Hartree)")
ax.set_title("H + H → H₂ Reaction Energy Diagram")

# Plot theoretical energy levels
ax.hlines(
y=2 * E_H_theo, xmin=0.5, xmax=1.3, linewidth=2, color="r", label="2H (Exact)"
)
ax.hlines(y=E_H2_theo, xmin=1.3, xmax=2, linewidth=2, color="b", label="H₂ (Exact)")

# Plot experimental energy levels
ax.hlines(
y=2 * E_H_exp,
xmin=0.5,
xmax=1.5,
linewidth=2,
color="r",
linestyle="dashed",
label="2H (VQE)",
)
ax.hlines(
y=E_H2_exp,
xmin=1.5,
xmax=2.5,
linewidth=2,
color="b",
linestyle="dashed",
label="H₂ (VQE)",
)

# Add labels
ax.text(
1,
2 * E_H_theo,
f"2H: {2*E_H_theo:.4f}",
verticalalignment="top",
horizontalalignment="left",
)
ax.text(
2,
E_H2_theo,
f"H₂: {E_H2_theo:.4f}",
verticalalignment="top",
horizontalalignment="left",
)
ax.text(
1,
2 * E_H_exp,
f"2H_VQE: {2*E_H_exp:.4f}",
verticalalignment="bottom",
horizontalalignment="right",
)
ax.text(
2,
E_H2_exp,
f"H₂_VQE: {E_H2_exp:.4f}",
verticalalignment="bottom",
horizontalalignment="right",
)

# Add arrows for reaction energy with ΔE label in the middle
mid_y_theo = (2 * E_H_theo + E_H2_theo) / 2
mid_y_exp = (2 * E_H_exp + E_H2_exp) / 2
ax.annotate(
"",
xy=(1.3, E_H2_theo),
xytext=(1.3, 2 * E_H_theo),
arrowprops=dict(arrowstyle="<->", color="g"),
)
ax.text(
1.35, mid_y_theo, f"ΔE: {E_reaction_theo:.4f}", color="g", verticalalignment="top"
)

ax.annotate(
"",
xy=(1.5, E_H2_exp),
xytext=(1.5, 2 * E_H_exp),
arrowprops=dict(arrowstyle="<->", color="g", linestyle="dashed"),
)
ax.text(
1.55,
mid_y_exp,
f"ΔE_VQE: {E_reaction_exp:.4f}",
color="g",
verticalalignment="center",
)

# Add legend
ax.legend()

plt.show()

Output of the previous code cell

كما هو مبيَّن في الشكل، على الرغم من وجود بعض الأخطاء، فإن طاقة الحالة الأساسية الدقيقة للهاميلتونيات وطاقة التفاعل المحسوبة باستخدام نتائج VQE متقاربتان، إذ تقتربان من -0.2 هارتري.

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

لنستعرض ملخصاً لما تعلمناه حتى الآن.

بدأنا أولاً باستعراض تقنيتين تقريبيتين مهمتين لحل مسائل الكيمياء الكمومية: مبدأ التنويع وخيارات مجموعات الدوال الأساسية، اللتين تُعدَّان أساسيتين لـ VQE. استكشفنا مبدأ التنويع يدوياً من خلال حساب طاقة الحالة الأساسية للمذبذب التوافقي البسيط.

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

وأخيراً، استخدمنا طاقات الحالة الأساسية المحسوبة لـ HH وH2H_2 التي حصلنا عليها عبر VQE لحساب طاقة التفاعل للعملية H+HH2H + H \rightarrow H_2.

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

المراجعة والأسئلة

المفاهيم الأساسية:

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

صح أم خطأ

  1. ينص مبدأ التنويع على أن القيمة المتوقعة للطاقة لأي دالة موجية تجريبية تكون دائماً أكبر من أو تساوي طاقة الحالة الأساسية الحقيقية.
  2. مجموعة الدوال الأساسية هي مجموعة من الدوال تُستخدم لتقريب الدوال الموجية الكمومية.
  3. VQE خوارزمية كمومية تُستخدم للحل الدقيق لمعادلة شرودينغر لهاميلتوني معطى.
  4. في VQE، تُستخدم دائرة كمومية ذات معاملات (ansatz) لتحضير الدوال الموجية التجريبية.
  5. اختيار المحسِّن في VQE (مثلاً COBYLA أو SPSA أو ADAM) لا يؤثر على جودة النتيجة.
  6. يُستخدم Estimator في Qiskit لحساب القيم المتوقعة للهاميلتونيات مباشرةً في VQE.

أسئلة الاختيار من متعدد:

  1. ما الغرض من الهاميلتوني في VQE؟
  • أ) توليد حالات كمومية عشوائية
  • ب) تحديد طاقة الحالات الكمومية
  • ج) تحسين الدوائر الكمومية
  • د) إنشاء التشابك الكمومي
  1. ما الهدف الأساسي لخوارزمية VQE؟
  • أ) إيجاد طاقة الحالة الأساسية لهاميلتوني معين
  • ب) إنشاء التشابك بين الكيوبتات
  • ج) تنفيذ بحث غروفر
  • د) كسر تشفير RSA
  1. كم عدد الحالات الكمومية التي يتم توليدها في هذا الدفتر لمقارنة الـ ansatz؟
  • أ) 100
  • ب) 1000
  • ج) 5000
  • د) 10,000
  1. لماذا يُستلزم وجود محسِّن كلاسيكي في VQE؟
  • أ) لإجراء القياسات الكمومية
  • ب) لتحديث معاملات الـ ansatz بهدف تقليل الطاقة
  • ج) لتشابك الكيوبتات
  • د) لتوليد عشوائية كمومية
  1. لماذا يُصمَّم الـ ansatz ليكون ذا معاملات؟
  • أ) للسماح بتحضير الحالة الكمومية
  • ب) للسماح بالبحث في فضاء واسع من الحالات الكمومية
  • ج) لتقليل تعقيد الدائرة
  • د) لقياس القيم الذاتية مباشرةً
  1. أيٌّ من العبارات التالية هي الأصح بشأن اختيار ansatz جيد؟
  • أ) يجب أن ينتج الـ ansatz حالات موزعة بالتساوي على كرة بلوخ وإلا فسيفشل.
  • ب) ينبغي تصميم الـ ansatz بما يتناسب مع نظامك لضمان قدرته على توليد حالات قريبة من الحالة الأساسية.
  • ج) ينبغي أن ينتج الـ ansatz حالات عشوائية باستخدام معاملاته التنويعية.
  • د) الـ ansatz الأفضل يمتلك دائماً عدداً أكبر من المعاملات التنويعية.

(Optional) الملحق: العبء الإضافي للمُحسِّن بحسب تعقيد الـ ansatz

يواجه VQE عدة تحديات معروفة[ref 6]، وفيما يلي التحديات المرتبطة بما تعلمناه أعلاه.

  1. تحديات اختيار الـ ansatz

ثمة تحدٍّ متأصل في اختيار الـ ansatz التغايري المناسب. فالـ ansätze المستوحاة من الكيمياء (كـ UCCSD) توفر دقةً فيزيائيةً عالية، لكنها تتطلب دوائر عميقة، بينما تمتلك الـ ansätze الكفوءة للعتاد دوائر أضحل، غير أنها قد تفتقر إلى قابلية التفسير الفيزيائي. علاوةً على ذلك، تُدخِل كثيرٌ من الـ ansätze معاملاتٍ تغايريةً زائدة لا تُسهم كثيراً في تحسين الدقة، لكنها تزيد صعوبة التحسين بشكل ملحوظ.

  1. صعوبات التحسين

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

  1. العبء الإضافي للمُحسِّن

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

سنلقي هنا نظرةً على هذه التحديات باستخدام VQE لجزيء H2H_2، مع نوعين مختلفين من الـ ansätze.

(ملاحظة: قد يستهلك هذا وقتاً أطول على وحدة المعالجة الكمية، لذا لا تتردد في استخدام محاكٍ إن لم يكن لديك وقت كافٍ.)

from qiskit.circuit import ParameterVector

num_iter = 4
alpha = ParameterVector("alpha", 3)
beta = ParameterVector("beta", 3 * num_iter)

# step1: Map problem to quantum circuits and operators
hamiltonian = SparsePauliOp.from_list(
[("I", -1.04886087), ("Z", -0.7967368), ("X", 0.18121804)]
)

ansatz_1 = ansatz3
ansatz_2 = QuantumCircuit(1)
for i in range(num_iter):
ansatz_2.rx(beta[i * 3 + 0], 0)
ansatz_2.rz(beta[i * 3 + 1], 0)
ansatz_2.rx(beta[i * 3 + 2], 0)
ansatz_1.draw("mpl")

Output of the previous code cell

ansatz_2.draw("mpl")

Output of the previous code cell

# Step 2: Optimize for target hardware

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)

ansatz_isa_1 = pm.run(ansatz_1)
ansatz_isa_2 = pm.run(ansatz_2)
hamiltonian_isa_1 = hamiltonian.apply_layout(layout=ansatz_isa_1.layout)
hamiltonian_isa_2 = hamiltonian.apply_layout(layout=ansatz_isa_2.layout)

لنشغّل الآن VQE بنقطة بداية مؤلفة من أحادٍ كلها، بحد أقصى 20 خطوة، ولنقارن تقارب كلا التشغيلين.

# QPU time 3m 40s for ibm_brisbane
# Step 3: Execute on target hardware

from scipy.optimize import minimize

x0 = np.ones(ansatz_1.num_parameters)

batch = Batch(backend=backend)

cost_history_dict = {
"prev_vector": None,
"iters": 0,
"cost_history": [],
}
estimator = Estimator(mode=batch)
estimator.options.default_shots = 2048

res = minimize(
cost_func,
x0,
args=(ansatz_isa_1, hamiltonian_isa_1, estimator),
method="cobyla",
options={"maxiter": 20},
)

batch.close()
Iters. done: 1 [Current cost: -0.8782202668652658]
Iters. done: 2 [Current cost: -0.43473160695469165]
Iters. done: 3 [Current cost: -0.4076372093159749]
Iters. done: 4 [Current cost: -1.3587839859772106]
Iters. done: 5 [Current cost: -1.774529906754082]
Iters. done: 6 [Current cost: -1.541934983115727]
Iters. done: 7 [Current cost: -1.2732403113465345]
Iters. done: 8 [Current cost: -1.820842221085785]
Iters. done: 9 [Current cost: -1.8065762857059005]
Iters. done: 10 [Current cost: -1.8126394095981146]
Iters. done: 11 [Current cost: -1.8205831886180421]
Iters. done: 12 [Current cost: -1.8086715778994924]
Iters. done: 13 [Current cost: -1.8307676638629322]
Iters. done: 14 [Current cost: -1.8177328827556327]
Iters. done: 15 [Current cost: -1.8179426218088064]
Iters. done: 16 [Current cost: -1.8109239667991088]
Iters. done: 17 [Current cost: -1.824271872489647]
Iters. done: 18 [Current cost: -1.813167587671394]
Iters. done: 19 [Current cost: -1.824647343397313]
Iters. done: 20 [Current cost: -1.8219785311686143]
# Save Cost_history as a new list
ansatz_1_history = cost_history_dict["cost_history"]
# QPU time 3m 40s for ibm_brisbane

x0 = np.ones(ansatz_2.num_parameters)

batch = Batch(backend=backend)

cost_history_dict = {
"prev_vector": None,
"iters": 0,
"cost_history": [],
}
estimator = Estimator(mode=batch)
estimator.options.default_shots = 2048

res = minimize(
cost_func,
x0,
args=(ansatz_isa_2, hamiltonian_isa_2, estimator),
method="cobyla",
options={"maxiter": 20},
)

batch.close()
Iters. done: 1 [Current cost: -0.738191173881188]
Iters. done: 2 [Current cost: -0.42636037194506304]
Iters. done: 3 [Current cost: -1.3503788613797374]
Iters. done: 4 [Current cost: -0.9109204349776897]
Iters. done: 5 [Current cost: -0.9060873157510835]
Iters. done: 6 [Current cost: -0.7735065414083984]
Iters. done: 7 [Current cost: -1.586889197437709]
Iters. done: 8 [Current cost: -1.659215191584943]
Iters. done: 9 [Current cost: -1.245445981794618]
Iters. done: 10 [Current cost: -1.1608385766138023]
Iters. done: 11 [Current cost: -1.1551733876027737]
Iters. done: 12 [Current cost: -1.8143337768286332]
Iters. done: 13 [Current cost: -1.2510951563756598]
Iters. done: 14 [Current cost: -1.6918311531865413]
Iters. done: 15 [Current cost: -1.8163783305531838]
Iters. done: 16 [Current cost: -1.8434877732947152]
Iters. done: 17 [Current cost: -1.8461898233304472]
Iters. done: 18 [Current cost: -1.0346471214915485]
Iters. done: 19 [Current cost: -1.8322518854150687]
Iters. done: 20 [Current cost: -1.717144678705999]
ansatz_2_history = cost_history_dict["cost_history"]
fig, ax = plt.subplots()

# Define the constant function)
ax.plot(
range(cost_history_dict["iters"]),
ansatz_1_history,
label="Ansatz with 3 parameters",
)
ax.plot(
range(cost_history_dict["iters"]),
ansatz_2_history,
label="Ansatz with 12 parameters",
)
ax.set_xlabel("Iterations")
ax.set_ylabel("Cost (Hartree)")
plt.legend()
plt.draw()

Output of the previous code cell

يوضح الرسم البياني أعلاه بجلاء أن عملية تحسين الـ ansatz الذي يحتوي على متغيرات أكثر تستغرق وقتاً أطول للوصول إلى تقارب مستقر.

بدلاً من الاعتماد على دوائر أحادية القِبِت بسيطة وansatz مباشر، يزداد تعقيد التحسين حين تُستلزَم دوائر كمية أكبر وansätze ذات بنية أكثر تعقيداً. يُبرز هذا تحدياً معروفاً في VQEs: العبء الإضافي للمُحسِّن.

يواصل الباحثون تطوير منهجيات متقدمة متنوعة يمكنها استخدام أجهزة الكم في مسائل الكيمياء. يمكنك الوصول إلى مجموعة واسعة من المواد التعليمية على IBM Quantum Learning.

المراجع

  • [ref 1 ] Richard P. Feynman, Simulating Physics with Computers, International Journal of Theoretical Physics, 1982.
  • [ref 2] Marov, M.Y. (2015). The Structure of the Universe. In: The Fundamentals of Modern Astrophysics. Springer, New York, NY.
  • [ref 3] How to solve difficult chemical engineering problems with quantum computing, IBM Research Blog, 2023.
  • [ref 4] Y. Cao, J. Romero and A. Aspuru-Guzik, "Potential of quantum computing for drug discovery," in IBM Journal of Research and Development, vol. 62, no. 6, pp. 6:1-6:20, 1 Nov.-Dec. 2018
  • [ref 5] Present State of Molecular Structure Calculation, REv. Mod. Phys. 32, 170, 1960
  • [ref 6] Fedorov, D.A., Peng, B., Govind, N. et al. VQE method: a short survey and recent developments. Mater Theory 6, 2 (2022)