انتقل إلى المحتوى الرئيسي
هذا المشروع في مرحلة تجريبية. وجدت خطأ؟ افتح مشكلة على GitHub. لديك سؤال أو فكرة؟ اسأل في Discussions — نحب سماع ملاحظاتك!
كيف جودة الترجمة في هذه الصفحة؟

تأجيل حل التوقيت باستخدام stretch

تحتوي مواصفة لغة OpenQASM 3 على نوع stretch يتيح لك تحديد التوقيت النسبي للعمليات بدلاً من التوقيت المطلق. أُضيف دعم stretch كمدد للتعليمة Delay في Qiskit v2.0.0. يُحسم الحجم الفعلي لمدة stretch في وقت الترجمة، بعد معرفة المدة الدقيقة للبوابات المعايَرة. يسعى المترجم إلى تقليل مدة stretch إلى الحد الأدنى، مع مراعاة قيود التوقيت على qubit واحد أو أكثر. يمكنك بذلك التعبير عن تصميمات البوابات كتباعد البوابات بالتساوي (مثلاً لتنفيذ تسلسل فك اقتران بالصدى عالي الرتبة)، أو محاذاة تسلسل بوابات إلى اليسار، أو تطبيق بوابة طوال مدة دائرة فرعية معينة، وذلك دون معرفة التوقيت الدقيق.

أمثلة​

فك الاقتران الديناميكي​

من أكثر حالات استخدام stretch شيوعاً تطبيق فك الاقتران الديناميكي على qubit في حالة خمول بينما يخضع qubit آخر لعمليات شرطية.

على سبيل المثال، يمكننا استخدام stretch لتطبيق تسلسل فك الاقتران الديناميكي XX على qubit 1، طوال مدة الكتلة الشرطية المطبقة على qubit 0، كما يوضح الرسم التالي:

صورة توضيحية للدائرة التالية

ستبدو الدائرة المقابلة كما يلي. لاحظ أن زوجاً من الحواجز ضروري لتحديد حدود هذا التوقيت النسبي.

from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit.classical import expr

qubits = QuantumRegister(2)
clbits = ClassicalRegister(2)
circuit = QuantumCircuit(qubits, clbits)
(q0, q1) = qubits
(c0, c1) = clbits

# Add barriers to define the boundaries
circuit.barrier()
circuit.h(q0)
circuit.measure(q0, c0)
with circuit.if_test((c0, 1)) as else_:
circuit.h(q0)
with else_:
circuit.x(q0)

# Apply an XX DD sequence with stretch on qubit 1
s = circuit.add_stretch("s")
circuit.delay(s, q1)
circuit.x(q1)
circuit.delay(expr.mul(s, 2), q1)
circuit.x(q1)
circuit.delay(s, q1)
circuit.barrier()

محاذاة الجدولة​

يستخدم هذا المثال stretch لضمان محاذاة تسلسل البوابات بين حاجزين إلى اليسار، بصرف النظر عن مددها الفعلية:

from qiskit import QuantumCircuit
from numpy import pi

qc = QuantumCircuit(5)
qc.barrier()
qc.cx(0, 1)
qc.u(pi/4, 0, pi/2, 2)
qc.cx(3, 4)

a = qc.add_stretch("a")
b = qc.add_stretch("b")
c = qc.add_stretch("c")

# Use the stretches as Delay duration.
qc.delay(a, [0, 1])
qc.delay(b, 2)
qc.delay(c, [3, 4])
qc.barrier()
ملاحظة

عند استخدام stretch مع خدمة IBM Quantum Compute، يُضاف أي باقٍ ناتج عن حل stretch إلى أول تأخير يستخدم stretch.

مثال:

a = circuit.add_stretch("a")
circuit.barrier(q0, q1)
circuit.delay(100, q0)
circuit.delay(a, q1) # resolve to 26
circuit.x(q1) # duration: 8
circuit.delay(a, q1) # resolve to 25
circuit.x(q1) # duration: 8
circuit.delay(a, q1) # resolve to 25
circuit.x(q1) # duration: 8
circuit.barrier(q0, q1)

يُحسم الكود أعلاه إلى قيمة 25 مع باقٍ مقداره 1. سيُضاف الباقي إلى أول تأخير[a].

معادلة حل stretch: a+8+a+8+a+8=100=3∗a+24a + 8 + a + 8 + a + 8 = 100 = 3*a + 24

عرض قيم stretch في خدمة IBM Quantum Compute​

تُحسم القيمة الفعلية لمدة stretch في وقت الترجمة، بعد جدولة الدائرة. عند تشغيل مهمة Sampler في IBM Quantum Compute Service، يمكنك عرض قيم stretch المحسومة في بيانات التعريف لنتيجة المهمة. دعم stretch في Quantum Compute تجريبي حالياً، لذا تحتاج أولاً إلى تعيين خيار تجريبي لتفعيل استرجاعه، ثم الوصول إلى البيانات مباشرةً من بيانات التعريف كما يلي:

# Enable stretch value retrieval.
sampler.options.experimental = {
"execution": {
"stretch_values": True,
"scheduler_timing": True,
},
}

# Access the stretch values from the metadata.
job_result = job.result()
circuit_stretch_values = (
job_result[0].metadata["compilation"]["stretch_values"]
)

# Visualize the timing.
# Use the sliders at the bottom, the controls at the top, and the
# legend on the side of the output to customize the view.
draw_circuit_schedule_timing(ob.result()[0].metadata['compilation']
['scheduler_timing']['timing'])
ملاحظة

على الرغم من أن إجمالي وقت الدائرة يُعاد في بيانات التعريف "compilation"، إلا أن هذا ليس الوقت المستخدم في الفوترة (وقت QPU).

فهم مخرجات بيانات التعريف​

تُعيد بيانات التعريف stretch_values المعلومات التالية:

  • الاسم: اسم stretch المطبّق.

  • القيمة: القيمة الهدف المطلوبة.

  • الباقي: الباقي من حل stretch، والذي يُضاف إلى أول تأخير يستخدم stretch.

  • القيم الموسّعة: مجموعات من القيم تحدد بداية stretch ومدته.

مثال​

# Define the circuit
circuit = QuantumCircuit(4)
foo = circuit.add_stretch("foo")
bar = circuit.add_stretch("bar")
circuit.barrier()
circuit.cz(0, 1)
circuit.cz(0, 1)
circuit.cz(0, 1)
circuit.cz(0, 1)

circuit.delay(foo, 2)
circuit.x(2)
# 3*foo
circuit.delay(expr.mul(3, foo), 2)
circuit.x(2)
# 2*foo
circuit.delay(expr.mul(2, foo), 2)

circuit.delay(bar, 3)
circuit.x(3)
circuit.delay(bar, 3)

circuit.measure_all()

مخرجات بيانات التعريف​

[{'name': 'bar',
'value': 29,
'remainder': 1,
'expanded_values': [[1365, 30], [1404, 29]]},
{'name': 'foo',
'value': 8,
'remainder': 2,
'expanded_values': [[1365, 10], [1384, 24], [1417, 16]]}
]

تعتمد قيم المدة المُعادة على القيمة الهدف والباقي المحسوب. على سبيل المثال، هذه هي المدد المُعادة لـ foo:

  • foo value + remainder (8+2 = 10)

  • foo value * 3 (8 x 3 = 24)

  • foo value * 2 (8 x 2 = 16)

يمكنك استخدام التصور المرئي للمساعدة في فهم التوقيت والتحقق منه.

draw_circuit_schedule_timing(job.result()[0].metadata
['compilation']['scheduler_timing']['timing'])

في الصورة التالية، استناداً إلى مخرج المثال، يقابل foo تأخيرات stretch على Qubit 2. يبدأ أول تأخير stretch يستخدم foo عند نهاية init_play (1365). مدة stretch هي 10، لذا ينتهي هذا التأخير عندما تبدأ بوابة x (1365+10=1375). يمكنك تفسير التأخيرين الثاني والثالث بالمثل.

يظهر الناتج من أمر draw_circuit_schedule_timing.

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

للاطلاع على التفاصيل الكاملة، راجع موضوع تصور توقيت الدائرة.

قيود Quantum Compute​

دعم stretch في Quantum Compute تجريبي حالياً وله القيود التالية:

  • متغير stretch واحد على الأكثر لكل مجموعة qubits بين الحواجز (الضمنية والصريحة). مجموعة الـ qubits هي qubit واحد أو أكثر؛ ويجب أن تكون هذه المجموعات غير متداخلة.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    circuit.delay(a, (q0, q1))
    circuit.delay(b, q0) # Invalid because 2 stretches are applied on q0
  • المنطقة المحاطة بمجموعة من الحواجز تُسمى منطقة الحاجز. لا يمكن استخدام متغير stretch في مناطق حاجز متعددة.

    # Stretch a is used in two barrier regions
    a = circuit.add_stretch("a")
    circuit.barrier((q0, q1))
    circuit.delay(a, q0)
    circuit.barrier((q0, q1))
    circuit.delay(a, q0)
    circuit.barrier((q0, q1))

    توضيح لمخرج الكود السابق

  • تعابير stretch مقتصرة على الصيغة X*stretch + Y حيث X وY ثوابت من نوع عشري أو صحيح.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    c = circuit.add_stretch("c")

    # (a / b) * c is not supported
    circuit.delay(expr.mul(expr.div(a, b), c), q1)
  • تعابير stretch لا يمكن أن تتضمن إلا متغير stretch واحداً.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    circuit.delay(expr.add(a, b), 0)
  • لا يمكن أن تُحسم تعابير stretch إلى قيم تأخير سالبة. لا يستنتج المحلل الحالي قيود عدم السلبية.

    from qiskit.circuit import Duration

    circuit.barrier((q0, q1))
    circuit.delay(20, q1)
    # The length of this barrier region is 20dt, meaning the
    # equation for solving stretch 'a' is a + 40dt = 20dt, giving a = -20dt.
    circuit.delay(expr.add(a, Duration.dt(40)), q0)
    circuit.barrier((q0, q1))