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

الـ Ansatz

شاهد فيكتوريا ليبينسكا وهي تشرح ما هو الـ ansatz ولماذا يهمنا في سياق محل القيمة الذاتية الكمومي التغيّري (VQE).

المراجع

المقالات التالية مُشار إليها في الفيديو أعلاه.

كود الـ Ansatz

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

في هذا الدرس ستتعلم:

  • مجموعة الـ ansaetze الجاهزة المتاحة في مكتبة الدوائر
  • كيفية تحديد خصائص الـ ansatz أو تعديلها
  • كيفية بناء الـ ansatz الخاص بك
  • أمثلة على الـ ansaetze الجيدة والسيئة

تحتوي مكتبة دوائر Qiskit على فئات متعددة من الدوائر التي يمكن استخدامها كـ ansatz. هنا سنقصر نقاشنا على دوائر ثنائية الموضع (دوائر تتكون من بوابات تعمل على كيوبتين بحد أقصى في كل مرة). الـ Efficient SU2 هو أحد الـ ansaetze الأكثر شيوعاً.

تتكون دائرة efficient_su_2 من طبقات من عمليات الكيوبت الواحد ممتدة عبر SU(2)‏ (مجموعة الوحدة الخاصة من الدرجة 2، مثل بوابات دوران باولي) وتشابكات CX. هذا نمط إرشادي يمكن أن يكون مفيداً في خوارزميات الكم التغيّرية مثل VQE ودوائر التصنيف في تعلم الآلة الكمومي (QML).

سنبدأ بمثال على دائرة efficient_su2 بأربعة كيوبتات بنوعين من بوابات SU(2)‏، لنقل rx و y. كذلك نحدد مخطط التشابك وعدد التكرارات. إن اكتفيت باستخدام .draw() للدوائر، ستحصل على تمثيل مجرد إلى حد ما. يمكن الحصول على رسم دائرة أكثر وضوحاً باستخدام .decompose().draw()، وسنستخدم هنا output = "mpl".

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit.circuit.library import efficient_su2

SU2_ansatz = efficient_su2(4, su2_gates=["rx", "y"], entanglement="linear", reps=1)
print(SU2_ansatz.draw())
SU2_ansatz.decompose().draw(output="mpl")
┌──────────┐┌───┐     ┌──────────┐   ┌───┐
q_0: ┤ Rx(θ[0]) ├┤ Y ├──■──┤ Rx(θ[4]) ├───┤ Y ├─────────────────────
├──────────┤├───┤┌─┴─┐└──────────┘┌──┴───┴───┐ ┌───┐
q_1: ┤ Rx(θ[1]) ├┤ Y ├┤ X ├─────■──────┤ Rx(θ[5]) ├───┤ Y ├─────────
├──────────┤├───┤└───┘ ┌─┴─┐ └──────────┘┌──┴───┴───┐┌───┐
q_2: ┤ Rx(θ[2]) ├┤ Y ├────────┤ X ├─────────■──────┤ Rx(θ[6]) ├┤ Y ├
├──────────┤├───┤ └───┘ ┌─┴─┐ ├──────────┤├───┤
q_3: ┤ Rx(θ[3]) ├┤ Y ├────────────────────┤ X ├────┤ Rx(θ[7]) ├┤ Y ├
└──────────┘└───┘ └───┘ └──────────┘└───┘

Output of the previous code cell

تظهر بوابات SU(2)‏ في البداية والنهاية بالترتيب والعناصر كما هو محدد في su2_gates = [...]. مخطط التشابك linear يعني أن بوابات CX تتدرج عبر الكيوبتات المرقّمة، فتشابك الكيوبت 0 مع 1، ثم 1 مع 2، وهكذا على طول قطري في الدائرة. كما تتوقع، يضيف ضبط reps = 2 ببساطة طبقة تشابك وطبقة SU(2)‏ ختامية. ويقابل reps = nn طبقات من التشابك، مع طبقات SU(2)‏ بينها وعلى كل طرف.

SU2_ansatz2 = efficient_su2(
4, su2_gates=["rx", "y", "z"], entanglement="linear", reps=2
)
SU2_ansatz2.decompose().draw(output="mpl")

Output of the previous code cell

ثمة عدة مخططات تشابك أخرى. ومن أبرز اثنين منها: circular وfull. التشابك الدائري مطابق للتشابك الخطي، ولكن مع بوابة CX إضافية تشابك الكيوبت الأول والأخير. أما مخطط التشابك الكامل فيتضمن بوابة CX بين كل زوج من الكيوبتات. لاحظ أنه لدائرة من N كيوبت، يوجد N(N1)/2N(N-1)/2 من بوابات CXCX، مما قد يصبح مكلفاً حسابياً.

SU2_ansatz3 = efficient_su2(
4, su2_gates=["rx", "y", "z"], entanglement="circular", reps=1
)
SU2_ansatz3.decompose().draw(output="mpl")

Output of the previous code cell

SU2_ansatz4 = efficient_su2(4, su2_gates=["rx", "y", "z"], entanglement="full", reps=1)
SU2_ansatz4.decompose().draw(output="mpl")

Output of the previous code cell

يمكنك مراقبة أعماق دوائرك باستخدام .depth()‎، أو أحياناً .decompose().depth()‎.

print(SU2_ansatz4.decompose().depth())
11

تعميم لـ efficient_su2 هو دائرة ثنائية الموضع (two-local)، وهي بدورها حالة خاصة من دوائر n-local. تحتوي الدوائر ثنائية الموضع أيضاً على كتل SU(2)‏ (أو كتل دوران) وكتل تشابك. هنا يمكننا بحرية تحديد نوع بوابات التشابك التي نريدها، مثل بوابات CRX. في هذا المثال، جميع البوابات تقبل معاملاً، لكن لا يلزم أن يكون الأمر كذلك. يمكن مثلاً استخدام بوابات دوران Y وبوابات CX للتشابك.

from qiskit.circuit.library import n_local

rotation_blocks = ["ry"]
entanglement_blocks = ["crx"]
two_ansatz = n_local(
4, rotation_blocks, entanglement_blocks, "linear", insert_barriers=True, reps=2
)
two_ansatz.decompose().draw(output="mpl")

Output of the previous code cell

آخر الـ ansatz الذي سنناقشه بالاسم هو Pauli-two-design. تحتوي هذه الدائرة على دوران أوّلي RY(π/4)RY(\pi/4)، وتحتوي طبقات الدوران على دورانات باولي للكيوبت الواحد حيث يُختار المحور بشكل منتظم وعشوائي ليكون X أو Y أو Z. وتتكون طبقات التشابك من بوابات CZ المزدوجة بعمق إجمالي يبلغ اثنين. لاحظ الفارق في عمق التشابك (وإجمالي الدائرة) بين هذا pauli_two_design وبين efficient_su2 مثلاً.

from qiskit.circuit.library import pauli_two_design

PtwoD_ansatz = pauli_two_design(5, reps=1, seed=10599, insert_barriers=True)
PtwoD_ansatz.decompose().draw(output="mpl")

Output of the previous code cell

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

لبناء الـ ansatz الخاص بك، ببساطة أنشئ دائرة كمومية مع جعل مجموعة فرعية من البوابات دوالاً لعناصر متجه معاملات ("theta" في المثال ثلاثي الكيوبتات أدناه).

from qiskit import QuantumCircuit
from qiskit.circuit import ParameterVector

n = 3

theta = ParameterVector("θ", length=n)
qc = QuantumCircuit(n)
qc.h(0)
qc.h(2)
for i in range(n - 1):
qc.cx(i, i + 1)
qc.cz(0, n - 1)
qc.barrier()
for i in range(n):
qc.ry(theta[i], i)
qc.barrier()
qc.cz(0, n - 1)
for i in reversed(range(n - 1)):
qc.cx(i, i + 1)
qc.h(0)
qc.h(1)
own_ansatz = qc
print(own_ansatz.depth())
qc.draw("mpl")
9

Output of the previous code cell

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

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

n = 4

theta = ParameterVector("θ", length=n)
qc = QuantumCircuit(n)
qc.h(0)
qc.h(2)
for i in range(n - 2):
qc.cx(i, i + 1)
qc.cz(0, n - 2)
qc.barrier()
for i in range(n):
qc.ry(theta[i], i)
qc.barrier()
qc.cz(0, n - 2)
for i in reversed(range(n - 2)):
qc.cx(i, i + 1)
qc.h(0)
qc.h(1)
own_ansatz2 = qc
print(own_ansatz2.depth())
qc.draw("mpl")
9

Output of the previous code cell

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

su2_ansatz_long = efficient_su2(
4, su2_gates=["rx", "y", "z"], entanglement="linear", reps=4
)
print(su2_ansatz_long.decompose().depth())
su2_ansatz_long.decompose().draw(output="mpl")
24

Output of the previous code cell

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