الـ Ansatz
شاهد فيكتوريا ليبينسكا وهي تشرح ما هو الـ ansatz ولماذا يهمنا في سياق محل القيمة الذاتية الكمومي التغيّري (VQE).
المراجع
المقالات التالية مُشار إليها في الفيديو أعلاه.
- The theory of variational hybrid quantum-classical algorithms, McClean, et al.
- Quantum Chemistry in the Age of Quantum Computing, Cao, et al.
- Noisy intermediate-scale quantum (NISQ) algorithms, Bharti, et al.
- The Variational Quantum Eigensolver: A review of methods and best practices, Tilly, et al.
- Hardware-efficient Variational Quantum Eigensolver for Small Molecules and Quantum Magnets, Kandala, et al.
- Quantum computational chemistry, McArdle, et al.
كود الـ Ansatz
في الدرس السابق أنشأت هاميلتونياً يصف طاقة الجزيء المدروس، وعيّنته إلى صيغة مفيدة للحاسوب الكمومي. يستخدم VQE دائرة تغيّرية لإعداد الحالات الكمومية، ثم نستخدم تلك الحالات لتحديد قيمة التوقع للهاميلتوني (الطاقة). تُعدَّل معاملات الدائرة التغيّرية حتى يتقارب الحساب نحو أدنى قيمة توقع. في سياق الكيمياء الكمومية، ينبغي أن تكون هذه هي طاقة الحالة الأرضية. يتمحور هذا الدرس حول الدائرة التغيّرية المعروفة أيضاً بـالـ ansatz (كلمة ألمانية تعني "النهج" أو "الأسلوب"). في هذا الدرس ستتعلم:
- مجموعة الـ ansaetze الجاهزة المتاحة في مكتبة الدوائر
- كيفية تحديد خصائص الـ ansatz أو تعديلها
- كيفية بناء الـ ansatz الخاص بك
- أمثلة على الـ ansaetze الجيدة والسيئة
تحتوي مكتبة دوائر Qiskit على العديد من فئات الدوائر التي يمكن استخدامها كـ ansatz. هنا، سنقصر نقاشنا على الدوائر ثنائية المحلية (two-local) (دوائر تتكون من بوابات تعمل على كيوبتين على الأكثر في كل مرة). Efficient SU2 هو ansatz شائع الاستخدام.
تتكون دائرة efficient_su_2 من طبقات من عمليات كيوبت مفردة تمتد عبر SU(2) (مجموعة الوحدة الخاصة من الدرجة 2، مثل بوابات دوران باولي) وتشابكات CX. هذا نمط استكشافي (heuristic) يمكن أن يكون مفيدًا في الخوارزميات الكمومية التغايرية مثل VQE ودوائر التصنيف في تعلم الآلة الكمومي (QML).
سنبدأ بمثال دائرة efficient_su2 من أربعة كيوبتات مع نوعين من بوابات SU(2)، لنقل rx و y. كما نحدد مخطط تشابك وعدد التكرارات. إذا قمت ببساطة بـ .draw() للدوائر، ستحصل على تمثيل مجرد إلى حد ما. يمكن الحصول على مخطط دائرة أكثر وضوحًا باستخدام .decompose().draw()، وهنا سنستخدم `output = "mpl"'.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"qiskit": "qiskit"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
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 ├
└──────────┘└───┘ └───┘ └──────────┘└───┘
تظهر بوابات SU(2) في البداية والنهاية بالترتيب والعناصر المحددة في su2_gates = [...]. مخطط التشابك linear يعني أن بوابات CX تتنقل عبر الكيوبتات المرقمة، فتشابك 0 و1، ثم 1 و2، وهكذا، على طول خط قطري في الدائرة. كما قد تتوقع، فإن ضبط reps = 2 يضيف ببساطة طبقة تشابك وطبقة SU(2) ختامية. الإعداد reps = n يقابل n طبقات تشابك، مع طبقات SU(2) بينها وفي كل طرف.
SU2_ansatz2 = efficient_su2(
4, su2_gates=["rx", "y", "z"], entanglement="linear", reps=2
)
SU2_ansatz2.decompose().draw(output="mpl")
توجد عدة مخططات تشابك أخرى. اثنان جديران بالذكر هما circular و full. التشابك الدائري مطابق للتشابك الخطي، لكن مع بوابة CX إضافية تشابك الكيوبت الأول والأخير. يتضمن مخطط التشابك الكامل بوابة CX بين كل زوج من الكيوبتات. لاحظ أنه بالنسبة لدائرة من N كيوبت، فهذا يعني بوابة ، ويمكن أن يصبح مكلفًا حسابيًا.
SU2_ansatz3 = efficient_su2(
4, su2_gates=["rx", "y", "z"], entanglement="circular", reps=1
)
SU2_ansatz3.decompose().draw(output="mpl")
SU2_ansatz4 = efficient_su2(4, su2_gates=["rx", "y", "z"], entanglement="full", reps=1)
SU2_ansatz4.decompose().draw(output="mpl")
يمكنك مراقبة أعماق دوائرك باستخدام .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")
آخر ansatz سنناقشه بالاسم هو Pauli-two-design. تحتوي هذه الدائرة على دوران أولي بمقدار ، وتحتوي طبقات الدوران على دورانات باولي لكيوبت واحد، حيث يُختار المحور بشكل عشوائي منتظم ليكون 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")
هذه الدوائر التغايرية الجاهزة مسبقًا مفيدة كأساليب استكشافية سواء من حيث تحقيق مستوى مرغوب من التشابك أو من حيث الحد من عمق الدائرة. لكن ليس فيها شيء سحري. أنت حر في صنع دائرتك التغايرية الخاصة. وبالفعل قد يكون ذلك مفيدًا في الحالات التي تعرف فيها شيئًا عن تشابك الحالة المستهدفة لنظامك.
لإنشاء 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
بشكل عام، اختيار أفضل حالة تجربة (ansatz) هو فن؛ فأفضل 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
من المرجح أن تكون هذه الدائرة الأخيرة خيارًا سيئًا، لأن عمق البوابات مرتفع جدًا، وتكرار طبقة التشابك أربع مرات من غير المرجح أن يُنتج تطابقًا أفضل بشكل كبير مع الحالة الهدف مقارنة بتكرارها مرتين أو ثلاث مرات.
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
هذه الدوائر ليست "مكتملة" بمعنى أنه لا تزال هناك معاملات غير معروفة ومتغيرة يجب إدراجها في العديد من البوابات. يتم اختيار تلك المعاملات عن طريق تخمينات متتالية، وتحديث المعاملات لخفض قيمة التوقع لدالة التكلفة (في سياق الكيمياء، عادةً طاقة الحالة الأرضية). في بُعد واحد، أو حتى بضعة أبعاد، يكون هذا أمرًا بسيطًا. لكن الدائرة أعلاه تحتوي على 20 معاملًا متغيرًا، مما يعني أن إيجاد الحالة الهدف ذات الطاقة الدنيا يعني البحث في حالة ذات 20 بُعدًا (سبب آخر لعدم تضمين بوابات دائرة غير ضرورية). هنا يأتي دور خوارزميات التحسين الكلاسيكية، وهو موضوع الدرس التالي.