قطع الأسلاك بصياغة تعليمة `Move` ثنائية Qubit
في هذا البرنامج التعليمي، سنعيد بناء قيم التوقع لدائرة Circuit مؤلفة من سبعة Qubit، وذلك بتقسيمها إلى دائرتين Circuit كل منهما أربعة Qubit باستخدام قطع الأسلاك.
فيما يلي الخطوات التي سنتبعها في هذا نمط Qiskit:
- الخطوة 1: تعيين المسألة إلى دوائر Circuit ومؤثرات كمومية:
- تعيين هاميلتونيان على دائرة Circuit كمومية.
- الخطوة 2: التحسين للعتاد المستهدف [تستخدم الإضافة الخاصة بالقطع]:
- قطع الدائرة Circuit والعنصر القابل للرصد.
- نقل التجارب الفرعية عبر Transpiler للعتاد.
- الخطوة 3: التنفيذ على العتاد المستهدف:
- تشغيل التجارب الفرعية الناتجة عن الخطوة 2 باستخدام البدائي
Sampler.
- تشغيل التجارب الفرعية الناتجة عن الخطوة 2 باستخدام البدائي
- الخطوة 4: المعالجة اللاحقة للنتائج [تستخدم الإضافة الخاصة بالقطع]:
- دمج نتائج الخطوة 3 لإعادة بناء قيمة التوقع للعنصر القابل للرصد المعني.
الخطوة 1: التعيين
إنشاء دائرة Circuit للقطع
أولاً، نبدأ بدائرة Circuit مستوحاة من الشكل 1(a) في arXiv:2302.03366v1.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-cutting qiskit-aer qiskit-ibm-runtime
import numpy as np
from qiskit import QuantumCircuit
qc_0 = QuantumCircuit(7)
for i in range(7):
qc_0.rx(np.pi / 4, i)
qc_0.cx(0, 3)
qc_0.cx(1, 3)
qc_0.cx(2, 3)
qc_0.cx(3, 4)
qc_0.cx(3, 5)
qc_0.cx(3, 6)
qc_0.cx(0, 3)
qc_0.cx(1, 3)
qc_0.cx(2, 3)
<qiskit.circuit.instructionset.InstructionSet at 0x7f16ab191a80>
qc_0.draw("mpl")

تحديد عنصر قابل للرصد
from qiskit.quantum_info import SparsePauliOp
observable = SparsePauliOp(["ZIIIIII", "IIIZIII", "IIIIIIZ"])
الخطوة 2: التحسين
إنشاء دائرة Circuit جديدة مع وضع تعليمات Move في مواضع القطع المطلوبة
بالنظر إلى الدائرة Circuit أعلاه، نريد وضع قطعَين للأسلاك على خط Qubit الأوسط، بحيث يمكن فصل الدائرة Circuit إلى دائرتين Circuit كل منهما أربعة Qubit. إحدى طرق تحقيق ذلك هي وضع تعليمات Move ثنائية Qubit يدوياً تنقل الحالة من سلك Qubit إلى آخر. وتعليمة Move مكافئة مفاهيمياً لعملية إعادة ضبط على Qubit الثاني، تليها بوابة Gate من نوع SWAP. ويتمثل أثر هذه التعليمة في نقل حالة Qubit الأول (المصدر) إلى Qubit الثاني (الوجهة)، مع استبعاد الحالة الواردة لـ Qubit الثاني. ولكي يعمل هذا على النحو المقصود، من الضروري أن لا يشترك Qubit الثاني (الوجهة) في أي تشابك مع بقية النظام؛ وإلا فإن عملية إعادة الضبط ستتسبب في انهيار جزئي لحالة بقية النظام.
هنا، نبني دائرة Circuit جديدة بإضافة Qubit واحد إضافي مع وضع عمليات Move في مكانها. في هذا المثال، يمكننا إعادة استخدام Qubit واحد: يصبح Qubit المصدر لأول تعليمة Move هو Qubit الوجهة لتعليمة Move الثانية.
ملاحظة: كبديل للتعامل المباشر مع تعليمات Move، يمكن اختيار تحديد قطع الأسلاك باستخدام تعليمة CutWire أحادية Qubit. توجد دالة cut_wires لتحويل تعليمات CutWire إلى تعليمات Move على Qubit مخصصة حديثاً. غير أنه على عكس الطريقة اليدوية، لا تتيح هذه الطريقة التلقائية إعادة استخدام أسلاك Qubit. راجع دليل الإرشادات الخاص بـ CutWire للاطلاع على التفاصيل.
from qiskit_addon_cutting.instructions import Move
qc_1 = QuantumCircuit(8)
for i in [*range(4), *range(5, 8)]:
qc_1.rx(np.pi / 4, i)
qc_1.cx(0, 3)
qc_1.cx(1, 3)
qc_1.cx(2, 3)
qc_1.append(Move(), [3, 4])
qc_1.cx(4, 5)
qc_1.cx(4, 6)
qc_1.cx(4, 7)
qc_1.append(Move(), [4, 3])
qc_1.cx(0, 3)
qc_1.cx(1, 3)
qc_1.cx(2, 3)
qc_1.draw("mpl")

إنشاء عنصر قابل للرصد يتوافق مع الدائرة Circuit الجديدة
يتوافق هذا العنصر القابل للرصد مع observable، لكن يجب مراعاة سلك Qubit الإضافي الذي أُضيف بشكل صحيح (أي إدراج "I" في الفهرس 4). لاحظ أنه في Qiskit، يقابل تمثيل السلسلة النصية لـ Qubit-0 الحرفَ الأيمن في سلسلة باولي.
observable_expanded = SparsePauliOp(["ZIIIIIII", "IIIIZIII", "IIIIIIIZ"])
فصل الدائرة Circuit والعناصر القابلة للرصد
كما في البرامج التعليمية السابقة، سيُجمَّع Qubit التي تحمل تسمية قسم مشتركة معاً، وستُقطع البوابات Gates غير المحلية الممتدة عبر أكثر من قسم.
from qiskit_addon_cutting import partition_problem
partitioned_problem = partition_problem(
circuit=qc_1, partition_labels="AAAABBBB", observables=observable_expanded.paulis
)
subcircuits = partitioned_problem.subcircuits
subobservables = partitioned_problem.subobservables
bases = partitioned_problem.bases
تصور المسألة المحللة
subobservables
{'A': PauliList(['IIII', 'ZIII', 'IIIZ']),
'B': PauliList(['ZIII', 'IIII', 'IIII'])}
subcircuits["A"].draw("mpl")

subcircuits["B"].draw("mpl")

حساب عبء أخذ العينات للقطوع المختارة
نقطع هنا سلكَين، مما ينتج عنه عبء أخذ عينات يساوي .
لمزيد من المعلومات حول عبء أخذ العينات الناجم عن قطع الدائرة Circuit، راجع المواد التوضيحية.
print(f"Sampling overhead: {np.prod([basis.overhead for basis in bases])}")
Sampling overhead: 256.0