דלג לתוכן הראשי

הזנה קדמית קלאסית ובקרת זרימה (מעגלים דינמיים)

Package versions

הקוד בדף זה פותח תוך שימוש בדרישות הבאות. אנחנו ממליצים להשתמש בגרסאות אלו או בגרסאות חדשות יותר.

qiskit[all]~=2.4.0

מעגלים דינמיים הם כלים רבי עוצמה שבהם אפשר למדוד Qubits באמצע ביצוע מעגל קוונטי, ואז לבצע פעולות לוגיקה קלאסית בתוך המעגל, בהתבסס על תוצאות אותן מדידות אמצע-מעגל. תהליך זה ידוע גם בשם הזנה קדמית קלאסית. למרות שאלו עדיין ימיה הראשונים של ההבנה כיצד לנצל בצורה הטובה ביותר את המעגלים הדינמיים, קהילת המחקר הקוונטי כבר זיהתה מספר מקרי שימוש, כגון הבאים:

משפט if

משפט ה-if משמש לביצוע פעולות באופן מותנה בהתבסס על ערכו של סיבית קלאסי או רגיסטר.

בדוגמה הבאה, אנחנו מיישמים Gate הדמארד על Qubit ומודדים אותו. אם התוצאה היא 1, אז אנחנו מיישמים Gate X על ה-Qubit, מה שהאפקט שלו הוא היפוכו בחזרה למצב 0. לאחר מכן אנחנו מודדים את ה-Qubit שוב. תוצאת המדידה המתקבלת צריכה להיות 0 עם הסתברות של 100%.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister

qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
circuit = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits

circuit.h(q0)
circuit.measure(q0, c0)
with circuit.if_test((c0, 1)):
circuit.x(q0)
circuit.measure(q0, c0)
circuit.draw("mpl")

# example output counts: {'0': 1024}

Output of the previous code cell

ניתן לתת למשפט ה-with יעד השמה שהוא עצמו מנהל הקשר שניתן לאחסן ולהשתמש בו לאחר מכן ליצירת בלוק else, אשר מבוצע בכל פעם שתוכן בלוק ה-if אינו מבוצע.

בדוגמה הבאה, אנחנו מאתחלים רגיסטרים עם שני Qubits ושני סיביות קלאסיות. אנחנו מיישמים Gate הדמארד על ה-Qubit הראשון ומודדים אותו. אם התוצאה היא 1, אז אנחנו מיישמים Gate הדמארד על ה-Qubit השני; אחרת, אנחנו מיישמים Gate X על ה-Qubit השני. לבסוף, אנחנו מודדים גם את ה-Qubit השני.

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

circuit.h(q0)
circuit.measure(q0, c0)
with circuit.if_test((c0, 1)) as else_:
circuit.h(q1)
with else_:
circuit.x(q1)
circuit.measure(q1, c1)

circuit.draw("mpl")

# example output counts: {'01': 260, '11': 272, '10': 492}

Output of the previous code cell

בנוסף לתנאי על סיבית קלאסי בודד, ניתן גם להתנות על ערכו של רגיסטר קלאסי המורכב ממספר סיביות.

בדוגמה הבאה, אנחנו מיישמים Gates הדמארד על שני Qubits ומודדים אותם. אם התוצאה היא 01, כלומר ה-Qubit הראשון הוא 1 וה-Qubit השני הוא 0, אז אנחנו מיישמים Gate X על Qubit שלישי. לבסוף, אנחנו מודדים את ה-Qubit השלישי. שים לב שלשם הבהירות, בחרנו לציין את מצב הסיבית הקלאסית השלישית, שהוא 0, בתנאי ה-if. בציור המעגל, התנאי מסומן על ידי עיגולים על הסיביות הקלאסיות שמתנים עליהן. עיגול מלא מציין תנאי על 1, בעוד שעיגול עם מתאר מציין תנאי על 0.

qubits = QuantumRegister(3)
clbits = ClassicalRegister(3)
circuit = QuantumCircuit(qubits, clbits)
(q0, q1, q2) = qubits
(c0, c1, c2) = clbits

circuit.h([q0, q1])
circuit.measure(q0, c0)
circuit.measure(q1, c1)
with circuit.if_test((clbits, 0b001)):
circuit.x(q2)
circuit.measure(q2, c2)

circuit.draw("mpl")

# example output counts: {'101': 269, '011': 260, '000': 252, '010': 243}

Output of the previous code cell

ביטויים קלאסיים

מודול הביטויים הקלאסיים של Qiskit qiskit.circuit.classical מכיל ייצוג חקרני של פעולות זמן ריצה על ערכים קלאסיים במהלך ביצוע מעגל. בשל מגבלות חומרה, רק תנאי QuantumCircuit.if_test() נתמכים כרגע.

הדוגמה הבאה מראה שניתן להשתמש בחישוב הזוגיות ליצירת מצב GHZ בן n-Qubit באמצעות מעגלים דינמיים. ראשית, צור n/2n/2 זוגות Bell על Qubits סמוכים. לאחר מכן, חבר את הזוגות הללו יחד באמצעות שכבה של Gates CNOT בין הזוגות. לאחר מכן מודדים את ה-Qubit היעד של כל Gates CNOT הקודמים ומאפסים כל Qubit מדוד למצב 0\vert 0 \rangle. מיישמים XX על כל אתר שלא נמדד שעבורו זוגיות כל הסיביות הקודמות היא אי-זוגית. לבסוף, Gates CNOT מוחלים על Qubits המדודים כדי לשחזר את השזירה שאבדה במדידה.

בחישוב הזוגיות, האלמנט הראשון של הביטוי הנבנה כולל הרמת אובייקט Python mr[0] לצומת Value (הפונקציה lift משמשת להפיכת אובייקטים שרירותיים לביטויים קלאסיים). אין צורך בכך עבור mr[1] ורגיסטרים הקלאסיים האפשריים הבאים, מכיוון שהם קלטים ל-expr.bit_xor, וכל הרמה נחוצה נעשית אוטומטית במקרים אלה. ניתן לבנות ביטויים כאלה בלולאות ובמבנים אחרים.

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

num_qubits = 8
if num_qubits % 2 or num_qubits < 4:
raise ValueError("num_qubits must be an even integer ≥ 4")
meas_qubits = list(range(2, num_qubits, 2)) # qubits to measure and reset

qr = QuantumRegister(num_qubits, "qr")
mr = ClassicalRegister(len(meas_qubits), "m")
qc = QuantumCircuit(qr, mr)

# Create local Bell pairs
qc.reset(qr)
qc.h(qr[::2])
for ctrl in range(0, num_qubits, 2):
qc.cx(qr[ctrl], qr[ctrl + 1])

# Glue neighboring pairs
for ctrl in range(1, num_qubits - 1, 2):
qc.cx(qr[ctrl], qr[ctrl + 1])

# Measure boundary qubits between pairs,reset to 0
for k, q in enumerate(meas_qubits):
qc.measure(qr[q], mr[k])
qc.reset(qr[q])

# Parity-conditioned X corrections
# Each non-measured qubit gets flipped iff the parity (XOR) of all
# preceding measurement bits is 1
for tgt in range(num_qubits):
if tgt in meas_qubits: # skip measured qubits
continue
# all measurement registers whose physical qubit index < tgt
left_bits = [k for k, q in enumerate(meas_qubits) if q < tgt]
if not left_bits: # skip if list empty
continue

# build XOR-parity expression
parity = expr.lift(
mr[left_bits[0]]
) # lift the first bit to Value so it will be treated like a boolean.
for k in left_bits[1:]:
parity = expr.bit_xor(
mr[k], parity
) # calculate parity with all other bits
with qc.if_test(parity): # Add X if parity is 1
qc.x(qr[tgt])

# Re-entangle measured qubits
for ctrl in range(1, num_qubits - 1, 2):
qc.cx(qr[ctrl], qr[ctrl + 1])
qc.draw(output="mpl", style="iqp", idle_wires=False, fold=-1)

Output of the previous code cell

הצעדים הבאים

המלצות