חקירת אי-וודאות
למודול Qiskit in Classrooms הזה, על הסטודנטים להכין סביבת Python עובדת עם החבילות הבאות מותקנות:
qiskitv2.1.0 ומעלהqiskit-ibm-runtimev0.40.1 ומעלהqiskit-aerv0.17.0 ומעלהqiskit.visualizationnumpypylatexenc
כדי להתקין ולהגדיר את החבילות שלמעלה, ראה את המדרי ך התקנת Qiskit. כדי להריץ עבודות על מחשבים קוונטיים אמיתיים, על הסטודנטים לפתוח חשבון ב-IBM Quantum® בהתאם לשלבים במדריך הגדרת חשבון IBM Cloud שלך.
המודול הזה נבדק והשתמש ב-8 דקות של זמן QPU. זהו אומדן בלבד. השימוש בפועל שלך עשוי להשתנות. שתי חישובים גוזלי-זמן מסומנים ככאלה בהערות הכותרת וניתן לבצע אותם על סימולטורים אם הסטודנטים קצרים בזמן QPU. עם הסרתם, המודול דורש רק ~30 שניות של זמן QPU.
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-ibm-runtime
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'
צפה בסיור המודול של ד"ר Katie McCormick למטה, או לחץ כאן לצפייה ב-YouTube.
מבוא
כנראה שמעת על עיקרון אי-הוודאות, גם מחוץ לקורסי הפיזיקה שלך. ניסוח יומיומי נפוץ של אי-הוודאות הוא "על ידי הסתכלות על משהו, אתה משפיע עליו." זה בהחלט נכון. אבל דרך פיזיקלית יותר לתאר אי-וודאות היא שישנם אובסרבבלים פיזיקליים מסוימים שיש להם אי-תאימות המונעת מהם להיות ידועים בו-זמנית בדיוק שרירותי. סטודנטים רבים נתקלים לראשונה בזוג המשתנים הבלתי-תואמים ו-, כלומר המיקום לאורך ציר אחד הנקרא ציר , ותנע הקו לאורך אותו כיוון, בהתאמה. עבור משתנים אלו, האילוץ על אי-הוודאות נכתב כאן, נקרא "אי-הוודאות ב-", שיש לו אותה הגדרה כמו סטיית תקן בסטטיסטיקה, וניתן להגדירו כ מוגדר באותה הדרך. כאן, לא נגזור את יחס אי-הוודאות הזה; נציין שהוא עקבי עם הבנתנו של גלים קלאסיים. כלומר, גל עם תדר ואורך גל אחד מושלם יימשך לנצח כסינוסואיד מושלם. מבחינה קוונטית-מכאנית, זה יתאים לידיעת התנע בצורה מושלמת לפי השערתו של דה ברויי: . אבל כדי לדעת חלקיק דמוי-גל נמצא, הגל המתאר אותו חייב להיות חד יותר במרחב, כמו גאוסיאן צר מאוד, למשל. אנחנו יודעים שניתן לבטא כל פונקציה רציפה, כולל פונקציות גל חדות כאלו, כסדרת פורייה של פונקציות סינוסואידליות עם אורכי גל שונים. אבל ככל שפונקציית הגל נעשית חדה יותר (והמיקום ידוע טוב יותר), נזדקק ליותר איברים בסדרת פורייה, כלומר תערובת של יותר אורכי גל (וכך, מבחינה קוונטית-מכאנית, יותר ערכים של תנע).
במילים פשוטות יותר: מצב עם תנע מוגדר היטב (סינוסואיד מושלם במרחב) יש לו מיקום מאוד לא-וודאי. מצב עם מיקום מוגדר היטב (כמו פילוג דלתא של דיראק) יש לו תנע מאוד לא-וודאי.
ישנם משתנים אחרים שמציגים אי-תאימות כזו. לדוגמה, ספין של חלקיק עשוי להיות בעל השלכה מוגדרת היטב לאורך ציר אחד, אך אז אנחנו לא יודעים כלום על ההשלכה על ציר ניצב. לדוגמה, המצב (עבור Qubit או חלקיק ספין-1/2) יש לו השלכה מוגדרת לאורך ציר (של 1 בהקשר של Qubit, ושל ב הקשר של חלקיק ספין-1/2). אבל ניתן לכתוב מצב זה כסופרפוזיציה של שני מצבים שלכל אחד מהם יש השלכה מוגדרת היטב על ציר : או שקולם ל- יש השלכה מוגדרת על , וכך גם ל-. אז אם נציין את ההשלכה של מצב לאורך ציר , אין אנחנו יודעים את ההשלכה לאורך ציר . ואם נציין את ההשל כה על ציר , אין אנחנו יודעים את ההשלכה לאורך . ישנם הבדלים קטנים כאשר דנים בכך בהקשר של ספין ובהקשר של Qubit. אבל באופן כללי, מצבים עצמיים של מטריצות פאולי יש להם יחס מעניין שניתן לחקור. לאורך שיעור זה, נבדוק ניסיונית את האינטואיציה שלנו לאי-הוודאות במשתנים הבלתי-תואמים הללו, ונאמת שיחסי אי-וודאות מתקיימים על מחשבים קוונטיים של IBM®.
בדיקה פשוטה של אינטואיציה
בניסוי הראשון הזה ולאורך כל המודול, נשתמש במסגרת לחישוב קוונטי הידועה בשם "Qiskit patterns", המחלקת תהליכי עבודה לשלבים הבאים:
- שלב 1: מיפוי קל טים קלאסיים לבעיה קוונטית
- שלב 2: אופטימיזציה של הבעיה לביצוע קוונטי
- שלב 3: ביצוע באמצעות Qiskit Runtime Primitives
- שלב 4: עיבוד לאחר ביצוע וניתוח קלאסי
בדרך כלל נפעל לפי השלבים הללו, אם כי לא תמיד נסמן אותם במפורש.
בואו נתחיל בטעינת כמה חבילות הכרחיות כולל Runtime primitives. נבחר גם את המחשב הקוונטי הפנוי ביותר הזמין לנו.
יש קוד למטה לשמירת האישורים שלך בשימוש הראשון. הקפד למחוק מידע זה מהמחברת לאחר שמירתו בסביבה שלך, כדי שהאישורים שלך לא ישותפו בטעות כאשר אתה משתף את המחברת. ראה הגדרת חשבון IBM Cloud שלך ו-אתחול השירות בסביבה לא אמינה להנחיות נוספות.
from numpy import pi
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform', instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')
# Load saved credentials
service = QiskitRuntimeService()
# Load the Runtime primitive and session
from qiskit_ibm_runtime import (
Batch,
SamplerV2 as Sampler,
EstimatorV2 as Estimator,
)
# Use the least busy backend
backend = service.least_busy(min_num_qubits=127)
print(backend.name)
ibm_sherbrooke
אם סטודנט ממצה את זמן החישוב הקוונטי הזמין לו במהלך השיעור, ניתן לבטל את ההערה מהשורות למטה ולהשתמש בהן להגדרת סימולטור שמחקה חלקית את התנהגות הרעש של המחשב הקוונטי שנבחר לעיל.
# Import an estimator, this time from qiskit (we will import from Runtime for real hardware)
from qiskit_aer.primitives import SamplerV2, EstimatorV2
from qiskit_aer.noise import NoiseModel
# Generate the noise model from the backend properties
noise_model = NoiseModel.from_backend(backend)
noisy_sampler = SamplerV2(options={"backend_options": {"noise_model": noise_model}})
noisy_estimator = EstimatorV2(options={"backend_options": {"noise_model": noise_model}})
אולי תזכור שמצב עצמי של אופרטור אחד, Z, אינו מצב עצמי של אופרטור אחר X. נתבונן בכך כעת בצורה ניסיונית על ידי ביצוע מדידות לאורך הצירים ו-. למדידה לאורך , פשוט נשתמש ב-qc.measure(), כי מחשבים קוונטיים של IBM מובנים למדידה לאורך . אבל למדידה לאורך , עלינו לסובב את המערכת כדי להעביר בפועל את ציר לכיוון שלאורכו אנחנו מודדים. זה מושג עם Gate הדמארד. יש שלב דומה הנדרש למדידות לאורך . השלבים הנדרשים מאספים כאן לנוחות:
- למדידה לאורך :
qc.measure() - למדידה לאורך :
qc.h()ואזqc.measure() - למדידה לאורך :
qc.sdg(),qc.h(),qc.sואזqc.measure()
שלב 1: מיפוי קלטים קלאסיים לבעיה קוונטית
במקרה זה, שלב המיפוי הוא פשוט ביטוי המדידות והסיבובים המתוארים לעיל ב-Circuit קוונטי:
# Step 1: Map
# Import some general packages
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Add a first measurement
qc.measure(qr, cr[0])
qc.barrier()
# Change basis so that measurements made on quantum computer which normally tell us about z, now tell us about x.
qc.h(qr)
# Add a second measurement
qc.measure(qr, cr[1])
qc.draw("mpl")
שלב 2: אופטימיזציה של הבעיה לביצוע קוונטי
שלב זה לוקח את הפעולות שאנו רוצים לבצע ומבטא אותן במונחים של הפונקציונליות של מחשב קוונטי ספציפי. הוא גם ממפה את הבעיה שלנו על פריסת המחשב הקוונטי.
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
שלב 3: ביצוע באמצעות Qiskit Runtime primitives
ניתן להשתמש ב-Sampler לאיסוף סטטיסטיקות על המדידות. נבנה את ה-Sampler primitive להריץ על מחשב קוונטי אמיתי באמצעות mode = backend. ישנם מצבים אחרים לתהליכי עבודה אחרים, ונשתמש באחד מהם למטה. ה-Sampler ישמש על ידי קריאה לשיטת run() שלו עם רשימה של "pubs" (Primitive Unified Blocs). כל PUB מכיל עד שלושה ערכים שיחד מגדירים יחידת עבודה חישובית לביצוע על ידי ה-Estimator: Circuit, observables, פרמטרים. ניתן גם לספק רשימה של Circuit, רשימת observables, ורשימת פרמטרים. למידע נוסף, קרא את סקירת PUBs.
אנחנו רוצים להריץ על מחשב קוונטי אמיתי, כדי שנבצע ניסוי פיזיקה קוונטית אמיתי. אם תמצה את הזמן המוקצה לך על מחשבים קוונטיים אמיתיים, תוכל להוסיף הערה לקוד למטה עבור המחשב הקוונטי, ולבטל את ההערה מהקוד להרצה על סימולטור.
# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()
שלב 4: עיבוד לאחר ביצוע
זהו מקרה פשוט במיוחד של עיבוד לאחר ביצוע, שבו אנחנו פשוט מדמיינים את הספירות.
שים לב ש-Qiskit מסדר Qubit, מדידות ודברים אחרים על ידי רישום הפריט הממוספר הנמוך ביותר אחרון / בימין, מוסכמה המכונה "little-endian". משמעות הדבר היא שהעמודה למטה המסומנת "10" מתייחסת לספירות שבהן המדידה הראשונה נתנה "0", והמדידה השנייה נתנה "1".
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
אם המוסכמה הזו לא מוצאת חן בעיניך, ניתן להשתמש ב-marginal_counts לדמות את תוצאות כל מדידה בנפרד:
from qiskit.result import marginal_counts
plot_histogram(
marginal_counts(counts, indices=[0]), title="Counts after first measurement"
)
plot_histogram(
marginal_counts(counts, indices=[1]), title="Counts after second measurement"
)
כברירת מחדל, מצבים ב-Qiskit מאותחלים למצב . אז אין זה מפתיע שכמעט כל המדידות הראשונות נתנו . שים לב, לעומת זאת, שהייתה כמעט חלוקה שווה במדידה השנייה (זו שמספקת מידע על השלכות המצב על ). נראה שמצב זה שנותן לנו תוצאות צפויות מאוד של מדידות לאורך נותן לנו קבוצה מאוד לא-צפויה של תוצאות למדידות לאורך . בואו נחקור זאת.
מה יקרה אם נבצע את המדידות בסדר הפוך? יכולנו להתחיל בשימוש ב-Gate הדמארד כדי לקבל סטטיסטיקות על ההסתברות ש- יימדד ב-. לאחר מכן, למדידה השנייה, נחזור לבסיס באמצעות Gate הדמארד השני.
# Step 1:
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Change basis to measure along x.
qc.h(qr)
qc.measure(qr, cr[0])
qc.barrier()
# Change our basis back to z and make a second measurement
qc.h(qr)
qc.measure(qr, cr[1])
qc.draw("mpl")
# Step 2: Transpile the circuit for running on a quantum computer
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
כאן, נראה שיש לנו אפילו פחות ודאות! קודם לכן, לפחות ידענו מה יהיה תוצאת המדידה הראשונה, כעת יש לנו חלוקה די שווה בכל המצבים האפשריים. לא קשה מדי להבין מדוע קרה זאת. התחלנו ב-, שהוא תערובת 50-50 של ו-, לפי אז ברור שאמורה להיות הסתברות שווה לקבל את המצב + או - (ממופה ל-0 וּ-1 בגרף) למדידה הראשונה. המדידה לאורך מכווצת את המצב לתוך מצב עצמי או המצב העצמי . כל אחד מהמצבים האלה הוא תערובת 50-50 של ו-, לפי אז ברגע שהמערכת נמצאת במצב עצמי של , ברור שמדידות לאורך ייתנו גם וגם , ויעשו זאת עם הסתברות שווה בערך. אז הדוגמה הראשונה שלנו הראתה לנו שלמצבים מסוימים יהיו תוצאות מדידה צפויות מאוד עבור מדידות מסוימות, אך תוצאות בלתי-צפויות עבור מדידות אחרות. הדוגמה הנוכחית מראה לנו שניתן לעשות גרוע מזה. ישנם מצבים שיכולים לתת לנו תוצאות בלתי-צפויות לשתי המדידות, גם אם כל שאנחנו עושים הוא להחליף את סדר המדידות. בואו נחקור עד כמה כמות מסוימת וודאית או לא-וודאית עבור מצב נתון.
חישוב אי-ודאות
אנחנו יכולים לכמת את זה באמצעות אי-ודאות, או שונות. "אי-הודאות" מוגדרת לרוב כשורש הריבועי של "השונות" של ההתפלגות. כלומר, אי-הודאות של אובייקט נצפה מסומנת ומוגדרת כך:
במקרה של מטריצות פאולי, שבהן , זה הופך ל:
בואו ניישם את זה על דוגמה קונקרטית. נתחיל עם המצב ונקבע את אי-הודאות של האובייקט הנצפה במצב הזה.
בדוק את ההבנה שלך
חשב ידנית את אי-הודאות של במצב .
Answer
במצב הנתון, זה נותן:
אפשר ליצור מצב ראשוני שרירותי באמצעות qc.initialize(). שים לב שהתחביר ליחידה המדומה כאן הוא .
# Step 1: Map the problem into a quantum circuit
from qiskit.quantum_info import SparsePauliOp
import numpy as np
obs = SparsePauliOp("X")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run([[qc_isa, obs_isa]])
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)
-0.02408454165642664
לפי המשוואה שלנו למעלה, בואו נישאר עם אותו מצב, אבל עכשיו נמצא את ערך הציפייה של :
# Step 1: Map the problem into a quantum circuit
obs = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state to |+>_y
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run(pubs)
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)
0.04958271968581247
אפשר לעשות את אותה מתמטיקה כמו קודם, אבל היינו רואים שהשונות שוב קרובה מאוד ל-1.0. אפשר להסיק ש-. אכן זה קירוב נכון למצב שבחרנו. אבל האם אפשר לעשות טוב יותר? או גרוע יותר?
זכרו שיש יחס אי-ודאות בין המיקום לאורך כיוון אחד, ולתנע לאורך אותו כיוון, עבור משתנים אלה, הצורה המוכרת ביותר היא כנראה אם זה כל מה שאנחנו זוכרים, אולי נתפתה לחשוב ש- ו- יכולים גם הם להיות עם גבול בסיסי על אי-הודאות. אולי אי-אפשר שהמכפלה תגיע לאפס? בואו ננסה מצב אחר ונראה אם זה מתקיים. הפעם נשתמש ב- בואו נראה מה קורה. שים לב שבקוד למטה, ה-Estimator יכול לקבל שתי קבוצות של מעגלים ואובייקטים נצפים באותה הגשת עבודה.
# Step 1: Map the problem into a quantum circuit
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, obs1_isa), (qc_isa, obs2_isa)]
job = estimator.run(pubs)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc,obs1],[qc,obs2]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print("The expectation value of the first observable is: ", res[0].data.evs)
print("The expectation value of the second observable is: ", res[1].data.evs)
The expectation value of the first observable is: 1.0011036174126302
The expectation value of the second observable is: 0.0029429797670141016
ערך הציפייה של אמור להיות קרוב ל-1.0, אבל לא לעלות על 1.0. אל תדאג אם הוא עולה על 1.0 בכמות קטנה מאוד. אפשר לייחס זאת לגורמים כמו רעש ו/או שגיאת קריאה. למרות שזה נושא חשוב מאוד, אפשר להתעלם ממנו לעת עתה.
קיבלנו ערך ציפייה של שקרוב מאוד ל-1.0 (המתאים לשונות נמוכה מאוד ב-). זה הופך את מכפלת שתי השונות לנמוכה למדי:
למרות שזה לא בדיוק אפס, ערך זה ה ופך קטן בהשוואה לערכים העצמיים של אופרטורי פאולי (). ובכן, אולי תזכרו שיחס אי-הודאות בין מיקום ליניארי ותנע ניתן לכתיבה בצורה שונה, תוך שימוש מפורש ביחס הקומוטציה בין האופרטורים ו-:
כאשר
הוא הקומוטטור של ו-.
זוהי הצורה שניתן להרחיב בקלות ביותר לאופרטורי פאולי. באופן כללי, עבור שני אופרטורים ו-,
ובמקרה של מטריצות פאולי ו-, אנחנו צריכים את כדי לחשב
אנחנו מראים את זה כאן, ומשאירים חישובים דומים לקורא כתרגיל:
זו תשובה מקובלת לחלוטין, אבל עם עוד צעד אחד, אנחנו רואים
יחס אי-הודאות שלנו הופך אז ל:
בדוק את ההבנה שלך
קרא את השאלה למטה, חשוב על התשובה שלך, ואז לחץ על המשולש כדי לגלות את הפתרון.
קבע את ואת . השתמש בזה כדי לכתוב את יחסי אי-הודאות בין ו-, ובין ו-.
תשובה:
בשילוב עם יחס אי-הודאות הכללי, מקבלים
אמת את העקביות
לפני שנמשיך, בואו נבדוק שזה היה עקבי עם הממצא הקודם שלנו. השתמשנו במצב ומצאנו ש- עכשיו אנחנו יודעים שהמכפלה הזאת צריכה להיות גדולה מ- או שווה ל:
אז אכן, השתמש בשאלות למטה כדי לבנות אינטואיציה לגבי הממצאים האלה:
בדוק את ההבנה שלך
קרא את השאלות למטה, חשוב על התשובות שלך, ואז לחץ על המשולשים כדי לגלות את הפתרונות.
ענה על הסעיפים הבאים ביחד כסט:
(a) אילו מצבים היית מצפה שתהיה להם אי-ודאות אפס ב-?
(b) אילו מצבים היית מצפה שתהיה להם אי-ודאות אפס ב-?
(c) באילו מצבים היית מקבל ערך ציפייה אפסי ?
(d) האם התשובות לשאלות לעיל עקביות עם המקרה ?
(e) כתוב קוד לבדוק את זה במפורש באמצעות Estimator.
תשובות:
(a) אפשר לצפות שמצבים עצמיים של האופרטור יניבו אי-ודאות אפסית ב-. אכן, כשמשתמשים ב- מקבלים
(b) אפשר לצפות שמצבים עצמיים של האופרטור יניבו אי-ודאות אפסית ב-. אכן, כשמשתמשים ב- מקבלים
(c) אנחנו מצפים למצוא עבור כל מצבים שבהם, כאשר נמדדים, מניבים היטל חיובי על ציר ה- באותה תדירות כמו היטל שלילי. אלה כוללים את המצבים העצמיים של ו-.
(d) כן. היינו מצפים לערך קטן מאוד למכפלת אי-הוודאויות עבור מצבים עצמיים של או : זה יכול להתקיים כי גם היינו מצפים ש- עבור אותם מצבים. כך שיחס אי-הודאות יכול להתקיים.
(e) קוד כגון הבא יאמת את זה:
obs1 = SparsePauliOp.from_list(
[("X", 1.000)]
)
obs2 = SparsePauliOp.from_list(
[("Y", 1.000)]
)
obs3 = SparsePauliOp.from_list(
[("Z", 1.000)]
)
qc = QuantumCircuit(1,1)
qc.ry(pi/2,0)
job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001)
res=job.result()
כאשר התוצאות מחזירות את כל ערכי הציפייה. כדי לאחזר את כל ערכי הציפייה ולחשב אי-ודאויות, אפשר להשתמש ב:
xs=res[0].data.evs[0]
ys=abs(res[0].data.evs[1])
zs=res[0].data.evs[2]
import math
prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
ענה על הסעיפים הבאים ביחד כסט:
(a) האם אתה יכול לחשוב על מצב שבו תהיה לך ערך ציפייה גדול ?
(b) האם היית מצפה שאותו מצב יהיה לו אי-ודאות גדולה או קטנה ב-?
(c) האם היית מצפה שאותו מצב יהיה לו אי-ודאות גדולה או קטנה ב-?
(d) האם התשובות לשאלות לעיל עקביות עם המקרה ?
(e) כתוב קוד לבדוק את זה במפורש באמצעות Estimator.
תשובות:
(a) אנחנו מצפים למצוא עבור המצב העצמי של : .
(b) היינו מצפים ש- יהיה עם אי-ודאות גדולה במצב מכיוון שמדידת במצב זה תניב תוצאה חיובית ושלילית בתדירות/הסתברות שווה.
(c) היינו מצפים ש- יהיה עם אי-ודאות גדולה במצב מכיוון שמדידת במצב זה תניב תוצאה חיובית ושלילית בתדירות/הסתברות שווה.
(d) כן. היינו מצפים לערך גדול למכפלת אי-הוודאויות עבור מצבים עצמיים של ועבור בפרט. גם היינו מצפים ש- עבור אותו מצב. כך גם וגם גדולים למדי במצב זה, וסביר שיחס אי-הודאות יכול שוב להתקיים.
(e) קוד כגון הבא יאמת את זה:
obs1 = SparsePauliOp.from_list(
[("X", 1.000)]
)
obs2 = SparsePauliOp.from_list(
[("Y", 1.000)]
)
obs3 = SparsePauliOp.from_list(
[("Z", 1.000)]
)
qc = QuantumCircuit(1,1)
qc.rx(-pi/2,0)
job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001)
res=job.result()
כאשר התוצאות מחזירות את כל ערכי הציפייה. כדי לאחזר את כל ערכי הציפייה ולחשב אי-ודאויות, אפשר להשתמש ב:
xs=res[0].data.evs[0]
ys=abs(res[0].data.evs[1])
zs=res[0].data.evs[2]
import math
prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
בדיקת יחסי אי-הוודאות
הבדיקה למעלה הדגימה את תקפות יחסי אי-הוודאות רק עבור בחירה אחת של וקטור מצב . כדי לשכנע את עצמנו שזה עקבי עם ניסוי באופן כללי, כדאי לבצע חישובים דומים באמצעות Estimator עבור בחירות רבות של וקטור המצב. נתחיל בסיבוב וקטור המצב שלנו הרחק מציר , תוך שימוש ב-Gate מסוג RY כדי לייצר מצבים ראשוניים שונים באמצעות פרמטר .
# The calculation below uses approximately 3-4 minutes of QPU time.
# Step 1: Map the problem into a quantum circuit
from qiskit.circuit import Parameter
import numpy as np
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0>
theta = Parameter("θ")
qc.ry(theta, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()
# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])
# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()
שימו לב שהעקומה האדומה תמיד גדולה יותר מהעקומה הכתומה לפעמים מכפלת אי-הוודאות יורדת ומתקרבת יחסית לגבול, ולפעמים היא עולה ומתרחקת מהגבול, אבל היא תמיד מקיימת את יחס אי-הוודאות.
כמובן, ייתכן שזו לא הבדיקה הטובה ביותר של יחס אי-הוודאות, מאחר שהגבול שלנו תמיד קרוב מאוד לאפס. בואו נשתמש במצב קוונטי שיש לו היטל גדול יותר על eigenstates של . באופן ספציפי, נמשיך לסובב את כלפי מטה מציר בזוויות משתנות, אבל עכשיו נסובב גם את המצב המתקבל סביב בזווית כלשהי, אולי , ונראה מה קורה.
# The calculation below uses approximately 3-4 minutes of QPU time.
from qiskit.circuit import Parameter
import numpy as np
# Step 1: Map the problem to a quantum circuit
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0> along one plane, and then along a transverse direction.
theta = Parameter("θ")
qc.ry(theta, 0)
qc.rz(pi / 4, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()
# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])
# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()
עכשיו אנחנו רואים שהגבול על אי-הוודאות עומד בפני בדיקה אמיתית! העקומה האדומה מתקרבת הרבה יותר לעקומה הכתומה מאשר קודם. למעשה, בהיעדר רעש, יחס אי-הוודאות היה מגיע לרוויה מלאה () בנקודה אחת. בנוכחות רעש ושגיאות קריאה, לא צריך להיות מופתעים אם הרצה מסוימת מניבה לפעמים גדול מעט יותר מ- זו לא הפרה אמיתית של עיקרון אי-הוודאות; זה פשוט תוצאת לוואי של שגיאה שאינה אפסית.
בדקו את ההבנה שלכם
קראו את השאלות למטה, חשבו על התשובות שלכם, ולאחר מכן לחצו על המשולשים כדי לגלות את הפתרונות.
הסבירו כיצד תדחפו זאת לגבול המוחלט, כדי להפוך את לגדולה ככל האפשר?
תשובה:
הקוד כרגע מכיל שורות שמסובבות את המצב הראשוני ברירת המחדל , כלפי מטה מציר בזווית פרמטרית ואז גם סביב ציר בזווית מה שמסובב את וקטור המצב חלק מהדרך לכיוון ציר .
qc.ry(theta,0)
qc.rz(pi/4,0)
ניתן לשנות את הסיבוב סביב מ- ל-, ולסובב כל הדרך ל-eigenstate של :
qc.ry(theta,0)
qc.rz(pi/2,0)
לא יידרשו שינויים נוספים.
שנו את הקוד או העתיקו אותו ויישמו את הבדיקה של יחס אי-הוודאות עם ערך הציפייה של Y ממוקסם. האם יחס אי-הוודאות מתקיים?
תשובה:
נשתמש בדיוק בקוד מהדוגמה למעלה, עם
qc.rz(pi/2,0)
מוחלף במקום
qc.rz(pi/4,0).
הגרף המתקבל אמור להיראות כמו זה שלמטה, וכן, עיקרון אי-הוודאות אמור עדיין להיות תקף.

שנו את הקוד למעלה כדי ליצור תמונה דומה, שמדגימה שממדידות על המחשב הקוונטי המכפלה מתנהגת כפי שצריכה. בחרו כל קבוצת מצבים שתרצו.
תשובה:
נשתמש בדיוק בקוד מהדוגמה למעלה, ולמעשה נוכל להשתמש באותן התוצאות מלמעלה, רק תוך שימוש בערכי הציפייה כדי לחשב אי-ודאויות שונות. לדוגמה, נוכל להשתמש ב-
xs=res[0].data.evs[0]
ys=res[0].data.evs[1]
zs=abs(res[0].data.evs[2])
import math
delx = []
dely = []
prodxy=[]
for i in range(len(xs)):
delx.append((1-xs[i]*xs[i])**0.5)
dely.append((1-ys[i]*ys[i])**0.5)
prodxy.append(((1-xs[i]*xs[i])**0.5)*(1-ys[i]*ys[i])**0.5)
ונוכל לשרטט
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r'$\Delta$ X')
plt.plot(params, dely, label=r'$\langle$ Y $\rangle$')
plt.plot(params, zs, label=r'$\Delta$ Z')
plt.plot(params, prodxy, label=r'$\Delta$X $\Delta$Z')
plt.xlabel(r'$\theta$')
plt.ylabel('Expectation/Uncertainty Values')
plt.legend()
plt.show()
אתגר: כתבו קוד כדי לסרוק דרך ערכים רבים של , בדיוק כפי שסרקנו דרך ערכים רבים של , וצרו גרף תלת-ממדי שמראה שיחס אי-הוודאות לעולם לא מופר. בחרו כל observables שתרצו.
שאלות
מדריכים יכולים לבקש גרסאות של מחברות אלה עם מפתחות תשובות והנחיות לגבי מיקום בתוכניות לימוד נפוצות על ידי מילוי סקר קצר זה על אופן השימוש במחברות.
מושגי מפתח:
- קיימים יחסי אי-ודאות בין קבוצות רבות של observables פיזיקליים, כולל מיקום ותנע ליניארי, ורכיבי ספין.
- מטריצות פאולי אינן מתחלפות. זהו השתקפות מתמטית של העובדה שלא ניתן לדעת/לקבוע את כל רכיבי הספין בו-זמנית.
- מחשוב קוונטי עושה שימוש נרחב באופרטורי/מטריצות פאולי, לכן שימושי לדעת את יחס אי-הוודאות עבור אופרטורי פאולי, וכן עבור אופרטורי הספין הקשורים אליהם.
- נוסחה כללית לאי-הוודאות של שני אופרטורים ו- היא
- eigenstate של אופרטור כלשהו מניב אי-ודאות אפסית ב-observable הפיזיקלי הקשור לאותו אופרטור. אפילו ניסויית,
- eigenstate של אופרטור כלשהו יניב אי-ודאות גדולה יותר עבור אופרטור שאינו מתחלף עם .
- תוצאות ניסויות באמצעות מחשב קוונטי אמיתי מאשרות את האינטואיציה שאנו מקבלים מייצוגי מטריצות של אופרטורים פיזיקליים.
שאלות נכון/לא נכון:
- נ/לא נ — ניתן למדוד ו- בו-זמנית, אבל לא .
- נ/לא נ — ניתן למדוד ו- בו-זמנית, אבל לא .
- נ/לא נ — אופרטורי מיקום ליניארי ותנע ליניארי אינם מתחלפים.
- נ/לא נ — מחשבי קוונטום של IBM מודדים לאורך כברירת מחדל, לכן יש לבצע סיבוב כדי למדוד לאורך כל כיוון אחר.
- נ/לא נ — ה-Circuit למטה מודד ביעילות ואז .
שאלות רב-ברירה:
-
הדיאגרמה למטה מדגימה איזה מיחסי אי-הוודאות הבאים?
- א.
- ב.
- ג.
- ד. אף אחד מהאמורים

-
מהי הרצף הסטנדרטי לביצוע מדידה לאורך ?
- א. רק
qc.measure() - ב.
qc.h()ואזqc.measure() - ג.
qc.h(),qc.h()ואזqc.measure() - ד.
qc.h(),qc.s,qc.h()ואזqc.measure() - ה.
qc.sdg(),qc.h(),qc.sואזqc.measure() - ו.
qc.sdg(),qc.h(),qc.s,qc.h()ואזqc.measure()
- א. רק
-
איזה מהמצבים הבאים מניב את ערך הציפייה הגדול ביותר ?
- א.
- ב.
- ג. הנקרא גם
- ד. הנקרא גם
- ה. הנקרא גם
- ו. הנקרא גם
-
איזה מהמצבים הבאים מניב את אי-הוודאות הגדולה ביותר ?
- א.
- ב. הנקרא גם
- ג. הנקרא גם
- ד. א ו-ב שווים
- ה. ב ו-ג שווים
- ו. א, ב ו-ג שווים
שאלות לדיון:
-
האם מושג אי-הוודאות הזה מתנגש בצורה כלשהי עם הרעיון של ספין כחץ וקטורי במרחב קרטזי? ומה לגבי כדור הבלוך?
-
נניח שמכוונים מכשיר מדידה לאורך כיוון באמצע הדרך בין ציר לציר . מה קורה? האם ניתן לבצע מדידה לאורך כיוון זה? כיצד זה קשור לאי-ודאות ב- וב-?