Qubit, שערים ומעגלים קוונטיים
Kifumi Numata (19 Apr 2024)
לחץ/י כאן כדי להוריד את ה-PDF של ההרצאה המקורית. שים/י לב שחלק מקטעי הקוד עשויים להיות מיושנים, מכיוון שמדובר בתמונות סטט יות.
זמן QPU משוער להרצת הניסוי הזה הוא 5 שניות.
1. מבוא
ביטים, שערים ומעגלים הם אבני הבניין הבסיסיות של החישוב הקוונטי. תלמד/י חישוב קוונטי במודל המעגל באמצעות ביטים קוונטיים ושערים, וגם תסקור/י את הנושאים של סופרפוזיציה, מדידה וסבך קוונטי.
בשיעור זה תלמד/י:
- שערים של Qubit בודד
- ספירת Bloch
- סופרפוזיציה
- מדידה
- שערים של שני Qubit ומצב סבוך
בסוף ההרצאה תלמד/י על עומק המעגל, שהוא חיוני לחישוב קוונטי בסדר גודל של שימוש.
2. חישוב כדיאגרמה
כשמשתמשים ב-Qubit או בביטים, צריך לתפעל אותם כדי להפוך את הקלטים הקיימים לפלטים הרצויים. עבור התוכניות הפשוטות ביותר עם מספר קטן מאוד של ביטים, שימושי לייצג תהליך זה בדיאגרמה הידועה בשם דיאגרמת מעגל.
הדמות בפינה השמאלית התחתונה היא דוגמה למעגל קלאסי, ואילו הדמות בפינה הימנית התחתונה היא דוגמה למעגל קוונטי. בשני המקרים, הקלטים נמ צאים בצד שמאל והפלטים בצד ימין, בעוד שהפעולות מיוצגות על ידי סמלים. הסמלים המשמשים לפעולות נקראים "שערים", בעיקר מסיבות היסטוריות.
3. שער קוונטי של Qubit בודד
3.1 מצב קוונטי וספירת Bloch
מצב ה-Qubit מיוצג כסופרפוזיציה של ו-. מצב קוונטי שרירותי מיוצג כ
כאשר ו- הם מספרים מרוכבים כך ש-.
ו- הם וקטורים במרחב הוקטורי המרוכב הדו-ממדי:
לכן, מצב קוונטי שרירותי מיוצג גם כ
מכך ניתן לראות שמצב הביט הקוונטי הוא וקטור יחידה במרחב מכפלה פנימית מרוכב דו-ממדי עם בסיס אורתונורמלי של ו-. הוא מנורמל ל-1.
|\psi\rangle =\begin\{pmatrix\} \alpha \\ \beta \end\{pmatrix\} נקרא גם וקטור המצב (statevector).
מצב קוונטי של Qubit בודד מיוצג גם כ
כאשר ו- הם הזוויות של ספירת Bloch בתרשים הבא.
בתאי הקוד הבאים, נבנה חישובים בסיסיים מחלקים בסיסיים ב-Qiskit. נבנה מעגל ריק ולאחר מכן נוסיף פעולות קוונטיות, נדון בשערים ונמחיש את ההשפעות שלהם תוך כדי.
ניתן להריץ את התא ב-"Shift" + "Enter". ייבא/י את הספריות קודם.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer qiskit-ibm-runtime
# Import the qiskit library
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector
from qiskit_ibm_runtime import Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.visualization import plot_histogram
הכנת ה-Circuit הקוונטי
נצור ונצייר Circuit של Qubit בודד.
# Create the single-qubit quantum circuit
qc = QuantumCircuit(1)
# Draw the circuit
qc.draw("mpl")
שער X
שער ה-X הוא סיבוב של סביב ציר ה- של ספירת Bloch. החלת שער ה-X על מניבה , והחלת שער ה-X על מניבה , כך שזו פעולה דומה לשער NOT הקלאסי, והיא ידועה גם כהיפוך ביט. ייצוג המטריצה של שער ה-X מוצג למטה.
qc = QuantumCircuit(1) # Prepare the single-qubit quantum circuit
# Apply a X gate to qubit 0
qc.x(0)
# Draw the circuit
qc.draw("mpl")
ב-IBM Quantum®, המצב ההתחלתי מוגדר כ-, כך שה-Circuit הקוונטי לעיל בייצוג מטריצה הוא
עכשיו, בואו נריץ את ה-Circuit הזה באמצעות סימולטור statevector.
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.+0.j, 1.+0.j],
dims=(2,))
הוקטור האנכי מוצג כוקטור שורה, עם מספרים מרוכבים (החלק הדמיוני מסומן ב-).
שער H
שער Hadamard הוא סיבוב של סביב ציר הנמצא באמצע בין ציר ה- לציר ה- על ספירת Bloch. החלת שער ה-H על יוצרת מצב סופרפוזיציה כגון . ייצוג המטריצה של שער ה-H מוצג למטה.
qc = QuantumCircuit(1) # Create the single-qubit quantum circuit
# Apply an Hadamard gate to qubit 0
qc.h(0)
# Draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.70710678+0.j, 0.70710678+0.j],
dims=(2,))
זהו
מצב הסופרפוזיציה הזה כל כך נפוץ וחשוב, עד שניתן לו סמל משלו:
על ידי החלת שער ה- על , יצרנו סופרפוזיציה של ו- שבה מדידה בבסיס החישובי (לאורך ציר z בתמונת ספירת Bloch) תיתן לך כל מצב בהסתברויות שוות.
מצב
אפשר שניחשת שיש מצב מקביל:
כדי ליצור מצב זה, יש להחיל תחילה שער X כדי לקבל , ואז להחיל שער H.
qc = QuantumCircuit(1) # Create the single-qubit quantum circuit
# Apply a X gate to qubit 0
qc.x(0)
# Apply an Hadamard gate to qubit 0
qc.h(0)
# draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([ 0.70710678+0.j, -0.70710678+0.j],
dims=(2,))
זהו
החלת שער ה- על מניבה סופרפוזיציה שווה של ו-, אך הסימן של שלילי.
3.2 מצב קוונטי של Qubit בודד ואבולוציה יוניטרית
הפעולות של כל ה-Gate-ים שראינו עד כה היו יוניטריות, כלומר ניתן לייצגן באמצעות אופרטור יוניטרי. במילים אחרות, מצב הפלט מתקבל על ידי פעולה על המצב ההתחלתי עם מטריצה יוניטרית:
מטריצה יוניטרית היא מטריצה המקיימת
מבחינת פעולת המחשב הקוונטי, נאמר שהחלת Gate קוונטי על ה-Qubit מפתחת את המצב הקוונטי. Gate-ים נפוצים של Qubit בודד כוללים את הבאים.
Gate-י פאולי:
כאשר המכפלה החיצונית חושבה כך:
Gate-ים נוספים נפוצים של Qubit בודד:
המשמעות והשימוש בהם מתוארים בפירוט רב יותר בקורס יסודות המידע הקוונטי.
תרגיל 1
השתמש ב-Qiskit כדי ליצור Circuit-ים קוונטיים שמכינים את המצבים המתוארים להלן. לאחר מכן הרץ כל Circuit באמצעות סימולטור ה-statevector והצג את המצב המתקבל על כדור בלוך. כבונוס, נסה לנחש מה יהיה המצב הסופי על סמך אינטואיציה לגבי ה-Gate-ים והסיבובים בכדור בלוך.
(1)
(2)
(3)
טיפים: ניתן להשתמש ב-Z Gate באופן הבא:
qc.z(0)
פתרון:
### (1) XX|0> ###
# Create the single-qubit quantum circuit
qc = QuantumCircuit(1) ##your code goes here##
# Add a X gate to qubit 0
qc.x(0) ##your code goes here##
# Add a X gate to qubit 0
qc.x(0) ##your code goes here##
# Draw a circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([1.+0.j, 0.+0.j],
dims=(2,))
### (2) HH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.h(0)
qc.draw("mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([1.+0.j, 0.+0.j],
dims=(2,))
### (3) HZH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.z(0)
qc.h(0)
qc.draw("mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.+0.j, 1.+0.j],
dims=(2,))
3.3 מדידה
מדידה היא נושא תיאורטי מורכב מאוד. אבל במונחים מעשיים, ביצוע מדידה לאורך (כפי שכל מחשבי הקוונטום של IBM® עושים) פשוט כופה על מצב ה-Qubit לקפוץ למצב או , ואנחנו מצפינים את התוצאה.
- הוא ההסתברות שנקבל בעת המדידה.
- הוא ההסתברות שנקבל בעת המדידה.
לכן, ו- נקראים משרעות הסתברות. (ראה "כלל בורן")
לדוגמה, ל- יש הסתברות שווה להפוך ל- או בעת המדידה. ל- יש סיכוי של 75% להפוך ל-.
סימולטור Qiskit Aer
עכשיו, בוא נמדוד Circuit שמכין את הסופרפוזיציה בהסתברות שווה שהוזכרה למעלה. עלינו להוסיף Gate-י מדידה, שכן סימולטור Qiskit Aer מדמה חומרה קוונטית אידיאלית (ללא רעש) כברירת מחדל. הערה: הסימולטור Aer יכול גם להחיל מודל רעש המבוסס על מחשב קוונטי אמיתי. נחזור למודלי רעש מאוחר יותר.
# Create a new circuit with one qubits (first argument) and one classical bits (second argument)
qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0, 0) # Add the measurement gate
qc.draw(output="mpl")
עכשיו אנחנו מוכנים להריץ את ה-Circuit שלנו על סימולטור Aer. בדוגמה זו, נשתמש ב-shots=1024 כברירת מחדל, כלומר נמדוד 1024 פעמים. לאחר מכן נציג את הספירות האלו בהיסטוגרמה.
# Run the circuit on a simulator to get the results
# Define backend
backend = AerSimulator()
# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)
# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc])
result = job.result()
# Print the results
counts = result[0].data.c.get_counts()
print(counts)
# Plot the counts in a histogram
plot_histogram(counts)
{'0': 521, '1': 503}
אנחנו רואים ש-0 ו-1 נמדדו עם הסתברות של כמעט 50% כל אחד. למרות שרעש לא סומלץ כאן, המצבים עדיין הסתברותיים. לכן, בעוד שאנחנו מצפים לפיזור של 50-50 בערך, נדיר שנמצא בדיוק כזה. בדיוק כמו שהטלת מטבע 100 פעמים נדיר שתניב בדיוק 50 מופעים של כל צד.
4. Gate קוונטי רב-Qubit ושזירה
4.1 מעגל קוונטי רב-Qubit
אפשר ליצור מעגל קוונטי של שני Qubitים עם הקוד הבא. נחיל Gate מסוג H על כל Qubit.
# Create the two qubits quantum circuit
qc = QuantumCircuit(2)
# Apply an H gate to qubit 0
qc.h(0)
# Apply an H gate to qubit 1
qc.h(1)
# Draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j],
dims=(2, 2))
הערה: סדר הביטים ב-Qiskit
Qiskit משתמש בסימון Little Endian לסדר Qubitים וביטים, כלומר Qubit 0 הוא הביט הימני ביותר במחרוזות הביטים. לדוגמה: פירושו ש-q0 נמצא במצב וש-q1 נמצא במצב . חשוב לשים לב לכך, כי חלק מהספרות בחישוב קוונטי משתמשות בסימון Big Endian (Qubit 0 הוא הביט השמאלי ביותר), וכך גם חלק ניכר מהספרות של מכניקת הקוונטים.
דבר נוסף שראוי לשים לב אליו הוא שכאשר מציגים מעגל קוונטי, ממוקם תמיד בחלק העליון של המעגל. עם זאת בחשבון, המצב הקוונטי של המעגל לעיל ניתן לכתיבה כמכפלת טנסור של מצבים קוונטיים של Qubit בודד.
( )
המצב ההתחלתי של Qiskit הוא , ולכן כשמחילים על כל Qubit, המצב משתנה לסופרפוזיציה שווה.
כלל המדידה זהה למקרה של Qubit בודד — הסתברות למדידת היא .
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)

עכשיו בואו נמדוד את המעגל הזה.
# Create a new circuit with two qubits (first argument) and two classical bits (second argument)
qc = QuantumCircuit(2, 2)
# Apply the gates
qc.h(0)
qc.h(1)
# Add the measurement gates
qc.measure(0, 0) # Measure qubit 0 and save the result in bit 0
qc.measure(1, 1) # Measure qubit 1 and save the result in bit 1
# Draw the circuit
qc.draw(output="mpl")
עכשיו נשתמש שוב בסימולטור Aer כדי לאמת בצורה ניסויית שההסתברויות היחסיות של כל מצבי הפלט האפשריים אכן שווות בערך.
# Run the circuit on a simulator to get the results
# Define backend
backend = AerSimulator()
# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)
# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc])
result = job.result()
# Print the results
counts = result[0].data.c.get_counts()
print(counts)
# Plot the counts in a histogram
plot_histogram(counts)
{'10': 262, '01': 246, '00': 265, '11': 251}
כצפוי, המצבים , , , נמדדו כל אחד בערך ב-25%.
4.2 Gateים קוונטיים רב-Qubit
CNOT gate
Gate מסוג CNOT (שנקרא גם "controlled NOT" או CX) הוא Gate של שני Qubitים, כלומר פעולתו מערבת שני Qubitים בו-זמנית: Qubit הבקרה (control) ו-Qubit המטרה (target). ה-CNOT הופך את Qubit המטרה רק כאשר Qubit הבקרה נמצא במצב .
| קלט (target,control) | פלט (target,control) |
|---|---|
| 00 | 00 |
| 01 | 11 |
| 10 | 10 |
| 11 | 01 |
בואו נדמה תחילה את פעולת ה-Gate הדו-Qubit הזה כאשר q0 וגם q1 נמצאים במצב , ונקבל את וקטור המצב של הפלט. התחביר של Qiskit הוא qc.cx(control qubit, target qubit).
# Create a circuit with two quantum registers and two classical registers
qc = QuantumCircuit(2, 2)
# Apply the CNOT (cx) gate to a |00> state.
qc.cx(0, 1) # Here the control is set to q0 and the target is set to q1.
# Draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
dims=(2, 2))
כצפוי, הפעלת CNOT gate על לא שינתה את המצב, מכיוון ש-Qubit הבקרה היה במצב . נחזור לפעולת ה-CNOT שלנו. הפעם נחיל CNOT gate על ונראה מה קורה.
qc = QuantumCircuit(2, 2)
# q0=1, q1=0
qc.x(0) # Apply a X gate to initialize q0 to 1
qc.cx(0, 1) # Set the control bit to q0 and the target bit to q1.
# Draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
dims=(2, 2))
על ידי הפעלת CNOT gate, המצב הפך עכשיו ל-.
בואו נאמת את התוצאות האלה על ידי הרצת המעגל על סימולטור.
# Add measurements
qc.measure(0, 0)
qc.measure(1, 1)
# Draw the circuit
qc.draw(output="mpl")
# Run the circuit on a simulator to get the results
# Define backend
backend = AerSimulator()
# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)
# Run the job
sampler = Sampler(backend)
job = sampler.run([isa_qc])
result = job.result()
# Print the results
counts = result[0].data.c.get_counts()
print(counts)
# Plot the counts in a histogram
plot_histogram(counts)
{'11': 1024}
התוצאות אמורות להראות לך ש- נמדד בהסתברות של 100%.
4.3 שזירה קוונטית והרצה על מחשב קוונטי אמיתי
בואו נתחיל בהצגת מצב שזור ספציפי שחשוב במיוחד בחישוב קוונטי, ואז נגדיר את המונח "שזור":
ומצב זה נקרא מצב Bell.
מצב שזור הוא מצב המורכב ממצבים קוונטיים ו- שאינו יכול להיות מיוצג כמכפלת טנסור של מצבים קוונטיים נפרדים.
אם ל- הבא יש שני מצבים ו-:
אז מכפלת הטנסור של שני המצבים הללו היא
אבל אין מקדמים ו- שיכולים לקיים את שתי המשוואות הללו. לכן, אינו מיוצג כמכפלת טנסור של מצבים קוונטיים נפרדים ו-