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

بناء الدوائر

إصدارات الحزم

تم تطوير الكود في هذه الصفحة باستخدام المتطلبات التالية. نوصي باستخدام هذه الإصدارات أو أحدث منها.

qiskit[all]~=2.3.0

تتناول هذه الصفحة بشكل أعمق فئة QuantumCircuit في Qiskit SDK، وتستعرض بعض الأساليب الأكثر تقدمًا التي يمكنك استخدامها لإنشاء الدوائر الكمومية.

ما هي الدائرة الكمومية؟

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

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(2)
qc.qubits
[<Qubit register=(2, "q"), index=0>, <Qubit register=(2, "q"), index=1>]

يمكن دمج كائنات QuantumRegister وClassicalRegister المتعددة لإنشاء دائرة. ويمكن تسمية كل QuantumRegister وClassicalRegister أيضًا.

from qiskit.circuit import QuantumRegister, ClassicalRegister

qr1 = QuantumRegister(2, "qreg1") # Create a QuantumRegister with 2 qubits
qr2 = QuantumRegister(1, "qreg2") # Create a QuantumRegister with 1 qubit
cr1 = ClassicalRegister(3, "creg1") # Create a ClassicalRegister with 3 cbits

combined_circ = QuantumCircuit(
qr1, qr2, cr1
) # Create a quantum circuit with 2 QuantumRegisters and 1 ClassicalRegister
combined_circ.qubits
[<Qubit register=(2, "qreg1"), index=0>,
<Qubit register=(2, "qreg1"), index=1>,
<Qubit register=(1, "qreg2"), index=0>]

يمكنك معرفة فهرس Qubit وسجله باستخدام طريقة find_bit الخاصة بالدائرة وسماتها.

desired_qubit = qr2[0]  # Qubit 0 of register 'qreg2'

print("Index:", combined_circ.find_bit(desired_qubit).index)
print("Register:", combined_circ.find_bit(desired_qubit).registers)
Index: 2
Register: [(QuantumRegister(1, 'qreg2'), 0)]

إضافة تعليمة إلى الدائرة يُلحق التعليمة بسمة data الخاصة بالدائرة. يُظهر ناتج الكود التالي أن data هي قائمة من كائنات CircuitInstruction، ولكل منها سمة operation وسمة qubits.

qc.x(0)  # Add X-gate to qubit 0
qc.data
[CircuitInstruction(operation=Instruction(name='x', num_qubits=1, num_clbits=0, params=[]), qubits=(<Qubit register=(2, "q"), index=0>,), clbits=())]

أسهل طريقة لعرض هذه المعلومات هي استخدام طريقة draw، التي تُعيد تمثيلًا مرئيًا للدائرة. راجع تصور الدوائر للاطلاع على طرق مختلفة لعرض الدوائر الكمومية.

qc.draw("mpl")

Output of the previous code cell

يمكن أن تحتوي كائنات تعليمات الدائرة على دوائر "تعريف" تصف التعليمة بمصطلحات تعليمات أكثر أساسية. على سبيل المثال، يُعرَّف بوابة X باعتبارها حالة خاصة من بوابة U3، وهي بوابة أكثر عمومية لـ Qubit واحد.

# Draw definition circuit of 0th instruction in `qc`
qc.data[0].operation.definition.draw("mpl")

Output of the previous code cell

التعليمات والدوائر متشابهة في أنها تصف كلتاهما عمليات على البتات و Qubits، لكنها تخدم أغراضًا مختلفة:

  • تُعامَل التعليمات على أنها ثابتة، وعادةً ما تُعيد طرقها تعليمات جديدة (دون تغيير الكائن الأصلي).
  • صُمِّمت الدوائر للبناء عبر أسطر كثيرة من الكود، وكثيرًا ما تُعدِّل طرق QuantumCircuit الكائن الموجود.

ما هو عمق الدائرة؟

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

تُوضِّح بقية هذه الصفحة كيفية التعامل مع الدوائر الكمومية.

بناء الدوائر

تُضيف طرق مثل QuantumCircuit.h وQuantumCircuit.cx تعليمات محددة إلى الدوائر. لإضافة تعليمات إلى دائرة بشكل أعم، استخدم طريقة append. تأخذ هذه الطريقة تعليمةً وقائمةً من Qubits لتطبيق التعليمة عليها. راجع توثيق واجهة برمجة مكتبة الدوائر للاطلاع على قائمة التعليمات المدعومة.

from qiskit.circuit.library import HGate

qc = QuantumCircuit(1)
qc.append(
HGate(), # New HGate instruction
[0], # Apply to qubit 0
)
qc.draw("mpl")

Output of the previous code cell

لدمج دائرتين، استخدم طريقة compose. تقبل هذه الطريقة كائن QuantumCircuit آخر وقائمةً اختيارية من تعيينات Qubits.

ملاحظة

تُعيد طريقة compose دائرةً جديدة ولا تُعدِّل أيًّا من الدائرتين اللتين تعمل عليهما. لتعديل الدائرة التي تستدعي عليها طريقة compose، استخدم الوسيط inplace=True.

qc_a = QuantumCircuit(4)
qc_a.x(0)

qc_b = QuantumCircuit(2, name="qc_b")
qc_b.y(0)
qc_b.z(1)

# compose qubits (0, 1) of qc_a to qubits (1, 3) of qc_b respectively
combined = qc_a.compose(qc_b, qubits=[1, 3])
combined.draw("mpl")

Output of the previous code cell

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

inst = qc_b.to_instruction()
qc_a.append(inst, [1, 3])
qc_a.draw("mpl")

Output of the previous code cell

إذا كانت دائرتك أحادية (unitary)، يمكنك تحويلها إلى Gate باستخدام طريقة to_gate. كائنات Gate هي أنواع محددة من التعليمات تمتلك ميزات إضافية، مثل طريقة control التي تُضيف تحكمًا كموميًا.

gate = qc_b.to_gate().control()
qc_a.append(gate, [0, 1, 3])
qc_a.draw("mpl")

Output of the previous code cell

لرؤية ما يجري، يمكنك استخدام طريقة decompose لتوسيع كل تعليمة إلى تعريفها.

ملاحظة

تُعيد طريقة decompose دائرةً جديدة ولا تُعدِّل الدائرة التي تعمل عليها.

qc_a.decompose().draw("mpl")

Output of the previous code cell

قياس Qubits

تُستخدم القياسات لأخذ عيِّنات من حالات Qubits الفردية ونقل النتائج إلى سجل كلاسيكي. لاحظ أنه إذا كنت تُرسل الدوائر إلى بدائيّة Sampler، فإن القياسات مطلوبة. أما الدوائر المرسلة إلى بدائيّة Estimator فيجب ألا تحتوي على قياسات.

يمكن قياس Qubits باستخدام ثلاث طرق: measure وmeasure_all وmeasure_active. لمعرفة كيفية تصور نتائج القياس، راجع صفحة تصور النتائج.

  1. QuantumCircuit.measure : يقيس كل Qubit في المعامل الأول على البت الكلاسيكي المحدد في المعامل الثاني. تتيح هذه الطريقة تحكمًا كاملًا في مكان تخزين نتيجة القياس.

  2. QuantumCircuit.measure_all : لا تأخذ أي معامل ويمكن استخدامها للدوائر الكمومية التي لا تحتوي على بتات كلاسيكية مُعرَّفة مسبقًا. تُنشئ أسلاكًا كلاسيكية وتخزن نتائج القياس بالترتيب. على سبيل المثال، يُخزَّن قياس Qubit qiq_i في cbitmeasimeas_i). كما تُضيف حاجزًا قبل القياس.

  3. QuantumCircuit.measure_active : مشابهة لـ measure_all، لكنها تقيس فقط Qubits التي تحتوي على عمليات.

qc1 = QuantumCircuit(2, 2)
qc1.measure(0, 1)
qc1.draw("mpl", cregbundle=False)

Output of the previous code cell

qc2 = QuantumCircuit(2)
qc2.measure_all()
qc2.draw("mpl", cregbundle=False)

Output of the previous code cell

qc3 = QuantumCircuit(2)
qc3.x(1)
qc3.measure_active()
qc3.draw("mpl", cregbundle=False)

Output of the previous code cell

الدوائر ذات المعاملات

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

from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit import Parameter

angle = Parameter("angle") # undefined number

# Create and optimize circuit once
qc = QuantumCircuit(1)
qc.rx(angle, 0)
qc = generate_preset_pass_manager(
optimization_level=3, basis_gates=["u", "cx"]
).run(qc)

qc.draw("mpl")

Output of the previous code cell

يُنشئ الكود التالي تغييرات عديدة على هذه الدائرة ويعرض أحدها.

circuits = []
for value in range(100):
circuits.append(qc.assign_parameters({angle: value}))

circuits[0].draw("mpl")

Output of the previous code cell

يمكنك العثور على قائمة المعاملات غير المُعرَّفة في الدائرة من خلال سمة parameters الخاصة بها.

qc.parameters
ParameterView([Parameter(angle)])

تغيير اسم المعامل

افتراضيًا، تبدأ أسماء المعاملات في الدوائر ذات المعاملات بالبادئة x- مثلًا x[0]. يمكنك تغيير الأسماء بعد تعريفها، كما هو موضح في المثال التالي.

from qiskit.circuit.library import z_feature_map
from qiskit.circuit import ParameterVector

# Define a parameterized circuit with default names
# For example, x[0]
circuit = z_feature_map(2)

# Set new parameter names
# They will now be prefixed by `hi` instead
# For example, hi[0]
training_params = ParameterVector("hi", 2)

# Assign parameter names to the quantum circuit
circuit = circuit.assign_parameters(parameters=training_params)
Forgotten the method name? Try asking Qiskit Code Assistant.

الخطوات التالية

توصيات