דלג לתוכן הראשי
פרויקט זה בשלב בטא. מצאת באג? פתח issue ב-GitHub. יש שאלה או רעיון? שאל ב-Discussions — נשמח לשמוע ממך!
מה איכות התרגום בדף זה?

אלגוריתמים קוונטיים: אומדן פאזה

הערה

Kento Ueda (15 May 2024)

מחברת זו מספקת את המושגים הבסיסיים ואת היישום של טרנספורמציית פורייה הקוונטית (QFT) ואומדן הפאזה הקוונטי (QPE).

הורד את ה-PDF של ההרצאה המקורית. שים לב שחלק מקטעי הקוד עשויים להיות מיושנים כיוון שמדובר בתמונות סטטיות.

זמן QPU משוער להרצת הניסוי הוא 7 שניות.

1. מבוא​

טרנספורמציית פורייה הקוונטית (QFT)

טרנספורמציית פורייה הקוונטית היא המקבילה הקוונטית של טרנספורמציית פורייה הדיסקרטית הקלאסית. זוהי טרנספורמציה לינארית המוחלת על מצבים קוונטיים, הממפה בסיסי חישוב לייצוגי הבסיס של פורייה שלהם. ה-QFT ממלא תפקיד מרכזי באלגוריתמים קוונטיים רבים, ומציע שיטה יעילה לחילוץ מידע תקופתיות ממצבים קוונטיים. ניתן לממש את ה-QFT עם O(N2)O(N^2) פעולות באמצעות Gates קוונטיים כמו Hadamard gates ו-Control-Phase gates עבור NN qubits, מה שמאפשר האצה אקספוננציאלית על פני טרנספורמציית פורייה הקלאסית.

  • יישומים: זהו חלק יסודי באלגוריתמים קוונטיים כמו אלגוריתם שור לפירוק מספרים גדולים ולוגריתם דיסקרטי.

אומדן פאזה קוונטי (QPE)

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

  • יישומים: הוא יכול לפתור בעיות כמו מציאת ערכים עצמיים של מטריצות יוניטריות ודמיית מערכות קוונטיות.

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

2. יסודות טרנספורמציית פורייה הקוונטית (QFT)​

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_aer": "qiskit-aer", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram, plot_bloch_multivector
from qiskit.quantum_info import Statevector
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler

from numpy import pi

בהקבלה לטרנספורמציית פורייה הדיסקרטית, ה-QFT פועל על מצב קוונטי ∣X⟩=∑j=0N−1xj∣j⟩\vert X\rangle = \sum_{j=0}^{N-1} x_j \vert j \rangle עבור NN qubits וממפה אותו למצב הקוונטי ∣Y⟩=∑k=0N−1yk∣k⟩\vert Y\rangle = \sum_{k=0}^{N-1} y_k \vert k \rangle.

QFTN:∣j⟩↦1N∑k=0N−1ωNjk∣k⟩QFT_{N}: \vert j \rangle \mapsto \frac{1}{\sqrt{N}}\sum_{k=0}^{N-1}\omega_N^{jk} \vert k \rangle

כאשר ωNjk=e2πijkN\omega_N^{jk} = e^{2\pi i \frac{jk}{N}}.

או בייצוג מטריצה יוניטרית:

UQFT=1N∑j=0N−1∑k=0N−1ωNjk∣k⟩⟨j∣U_{QFT} = \frac{1}{\sqrt{N}} \sum_{j=0}^{N-1} \sum_{k=0}^{N-1} \omega_N^{jk} \vert k \rangle \langle j \vert

2.1. אינטואיציה ​

טרנספורמציית פורייה הקוונטית (QFT) עושה מיפוי בין שני בסיסים: בסיס החישוב (Z) ובסיס פורייה. אבל מה משמעות בסיס פורייה בהקשר זה? סביר להניח שאתה זוכר שטרנספורמציית פורייה F(ω)F(\omega) של פונקציה f(x)f(x) מתארת את הקונבולוציה של f(x)f(x) על פונקציה סינוסואידלית בתדר ω\omega. במילים פשוטות: טרנספורמציית פורייה היא פונקציה המתארת כמה מכל תדר ω\omega נצטרך כדי לבנות פונקציה f(x)f(x) מפונקציות סינוס (או קוסינוס). כדי לקבל תחושה טובה יותר למה ה-QFT אומר בהקשר זה, שקול את התמונות המדורגות למטה המציגות מספר המקודד בבינארי, באמצעות ארבעה qubits:

בבסיס החישוב, אנחנו מאחסנים מספרים בבינארי באמצעות המצבים ∣0⟩|0\rangle ו-∣1⟩|1\rangle.

שים לב לתדירות שבה qubits שונים משתנים; ה-Qubit השמאלי ביותר מתהפך עם כל תוספת במספר, הבא עם כל 2 תוספות, השלישי עם כל 4 תוספות, וכן הלאה.

אם נחיל טרנספורמציית פורייה קוונטית על מצבים אלה, נבצע מיפוי

∣State in Computational Basis⟩→QFT∣State in Fourier Basis⟩|\text{State in Computational Basis}\rangle \quad \xrightarrow[]{\text{QFT}} \quad |\text{State in Fourier Basis}\rangle QFT∣x⟩=∣x~⟩\text{QFT}|x\rangle = |\widetilde{x}\rangle

(לעיתים קרובות אנחנו מסמנים מצבים בבסיס פורייה באמצעות טילדה (~)).

בבסיס פורייה, אנחנו מאחסנים מספרים באמצעות סיבובים שונים סביב ציר ה-Z:

IFRAME

המספר שאנחנו רוצים לאחסן קובע את הזווית שבה כל qubit מסתובב סביב ציר ה-Z. במצב ∣0~⟩|\widetilde{0}\rangle, כל ה-Qubits נמצאים במצב ∣+⟩|{+}\rangle. כפי שנראה בדוגמה לעיל, כדי לקודד את המצב ∣5~⟩|\widetilde{5}\rangle על 4 qubits, סובבנו את ה-Qubit השמאלי ביותר ב-52n=516\tfrac{5}{2^n} = \tfrac{5}{16} סיבובים מלאים (516×2π\tfrac{5}{16}\times 2\pi רדיאנים). ה-Qubit הבא מסתובב כפליים מזה (1016×2π\tfrac{10}{16}\times 2\pi רדיאנים, או 10/1610/16 סיבובים מלאים), זווית זו מוכפלת שוב עבור ה-Qubit שאחריו, וכן הלאה.

שוב, שים לב לתדירות שבה כל qubit משתנה. ה-Qubit השמאלי ביותר (qubit 0) במקרה זה בעל התדר הנמוך ביותר, והימני ביותר בעל הגבוה ביותר.

2.2 דוגמה: QFT של qubit אחד​

נשקול את המקרה של N=21=2N = 2^1 = 2.

ניתן לכתוב את המטריצה היוניטרית:

UQFT=12∑j=01∑k=01ω2jk∣k⟩⟨j∣=12(ω20∣0⟩⟨0∣+ω20∣0⟩⟨1∣+ω20∣1⟩⟨0∣+ω21∣1⟩⟨1∣)=12(∣0⟩⟨0∣+∣0⟩⟨1∣+∣1⟩⟨0∣−∣1⟩⟨1∣)=H\begin{aligned} U_{QFT} & = \frac{1}{\sqrt{2}} \sum_{j=0}^{1} \sum_{k=0}^{1} \omega_2^{jk} \vert k \rangle \langle j \vert \\ & = \frac{1}{\sqrt{2}} (\omega_2^{0} \vert 0 \rangle \langle 0 \vert + \omega_2^{0} \vert 0 \rangle \langle 1 \vert + \omega_2^{0} \vert 1 \rangle \langle 0 \vert + \omega_2^{1} \vert 1 \rangle \langle 1 \vert) \\ & = \frac{1}{\sqrt{2}} (\vert 0 \rangle \langle 0 \vert + \vert 0 \rangle \langle 1 \vert + \vert 1 \rangle \langle 0 \vert - \vert 1 \rangle \langle 1 \vert) \\ & = H \end{aligned}

פעולה זו היא תוצאה של החלת שער ה-Hadamard (HH).

2.3 ייצוג מכפלה של QFT​

נכליל טרנספורמציה עבור N=2nN = 2^n, QFTNQFT_{N} הפועל על המצב ∣x⟩=∣x1…xn⟩\vert x \rangle = \vert x_1\ldots x_n \rangle.

QFTN∣x⟩=1N∑y=0N−1ωNxy∣y⟩=1N∑y=0N−1e2πixy/2n∣y⟩ since ωNxy=e2πixyN and N=2n=1N∑y=0N−1e2πi(∑k=1nyk/2k)x∣y1…yn⟩ rewriting in fractional binary notation y=y1…yn,y/2n=∑k=1nyk/2k=1N∑y=0N−1∏k=1ne2πixyk/2k∣y1…yn⟩ after expanding the exponential of a sum to a product of exponentials,=1N⨂k=1n(∣0⟩+e2πix/2k∣1⟩) after rearranging the sum and products, and expanding∑y=0N−1=∑y1=01∑y2=01…∑yn=01=1N(∣0⟩+e2πi2x∣1⟩)⊗(∣0⟩+e2πi22x∣1⟩)⊗…⊗(∣0⟩+e2πi2n−1x∣1⟩)⊗(∣0⟩+e2πi2nx∣1⟩)\begin{aligned} QFT_N\vert x \rangle & = \frac{1}{\sqrt{N}} \sum_{y=0}^{N-1}\omega_N^{xy} \vert y \rangle \\ & = \frac{1}{\sqrt{N}} \sum_{y=0}^{N-1} e^{2 \pi i xy / 2^n} \vert y \rangle ~\text{since}\: \omega_N^{xy} = e^{2\pi i \frac{xy}{N}} \:\text{and}\: N = 2^n \\ & = \frac{1}{\sqrt{N}} \sum_{y=0}^{N-1} e^{2 \pi i \left(\sum_{k=1}^n y_k/2^k\right) x} \vert y_1 \ldots y_n \rangle \:\text{rewriting in fractional binary notation}\: y = y_1\ldots y_n, y/2^n = \sum_{k=1}^n y_k/2^k \\ & = \frac{1}{\sqrt{N}} \sum_{y=0}^{N-1} \prod_{k=1}^n e^{2 \pi i x y_k/2^k } \vert y_1 \ldots y_n \rangle \:\text{after expanding the exponential of a sum to a product of exponentials,} \\ & = \frac{1}{\sqrt{N}} \bigotimes_{k=1}^n \left(\vert0\rangle + e^{2 \pi i x /2^k } \vert1\rangle \right) \:\text{after rearranging the sum and products, and expanding} \sum_{y=0}^{N-1} = \sum_{y_1=0}^{1}\sum_{y_2=0}^{1}\ldots\sum_{y_n=0}^{1} \\ & = \frac{1}{\sqrt{N}} \left(\vert0\rangle + e^{\frac{2\pi i}{2}x} \vert1\rangle\right) \otimes \left(\vert0\rangle + e^{\frac{2\pi i}{2^2}x} \vert1\rangle\right) \otimes \ldots \otimes \left(\vert0\rangle + e^{\frac{2\pi i}{2^{n-1}}x} \vert1\rangle\right) \otimes \left(\vert0\rangle + e^{\frac{2\pi i}{2^n}x} \vert1\rangle\right) \end{aligned}

2.4 דוגמה: בניית Circuit של QFT עם 3 qubits​

מהתיאור לעיל, אולי לא ברור כיצד לבנות Circuit של QFT. לעת עתה, פשוט שים לב שאנחנו מצפים לשלושה qubits שיהיו להם פאזות המתפתחות בקצבים "שונים". ההבנה של כיצד זה מתורגם ל-Circuit נשארת כתרגיל לקורא. ישנם מספר דיאגרמות ודוגמאות ב-PDF של ההרצאה. משאבים נוספים כוללים שיעור זה מקורס יסודות האלגוריתמים הקוונטיים.

נדגים את QFT באמצעות סימולטורים בלבד, ולכן לא נשתמש במסגרת Qiskit patterns עד שנעבור לאומדן פאזה קוונטי.

# Prepare for 3 qubits circuit
qr = QuantumRegister(3)
cr = ClassicalRegister(3)
qc = QuantumCircuit(qr, cr)
qc.h(2)
qc.cp(pi / 2, 1, 2) # Controlled-phase gate from qubit 1 to qubit 2
qc.cp(pi / 4, 0, 2) # Controlled-phase gate from qubit 0 to qubit 2
qc.draw(output="mpl")

Output of the previous code cell

qc.h(1)
qc.cp(pi / 2, 0, 1) # Controlled-phase gate from qubit 0 to qubit 1

qc.draw(output="mpl")

Output of the previous code cell

qc.h(0)

qc.draw(output="mpl")

Output of the previous code cell

qc.swap(0, 2)

qc.draw(output="mpl")

Output of the previous code cell

ננסה להחיל QFT על ∣5⟩|5\rangle כדוגמה.

ראשית, נאשר את הסימון הבינארי של המספר 5 וניצור את ה-Circuit המקודד את המצב 5:

bin(5)
'0b101'
qc = QuantumCircuit(3)

qc.x(0)
qc.x(2)
qc.draw(output="mpl")

Output of the previous code cell

נבדוק את המצבים הקוונטיים באמצעות סימולטור Aer:

statevector = Statevector(qc)
plot_bloch_multivector(statevector)

Output of the previous code cell

לבסוף, נוסיף QFT ונצפה במצב הסופי של ה-Qubits שלנו:

qc.h(2)
qc.cp(pi / 2, 1, 2)
qc.cp(pi / 4, 0, 2)

qc.h(1)
qc.cp(pi / 2, 0, 1)

qc.h(0)

qc.swap(0, 2)

qc.draw(output="mpl")

Output of the previous code cell

statevector = Statevector(qc)
plot_bloch_multivector(statevector)

Output of the previous code cell

אנחנו יכולים לראות שפונקציית ה-QFT שלנו עבדה נכון. Qubit 0 סובב ב-58\tfrac{5}{8} מסיבוב מלא, qubit 1 ב-108\tfrac{10}{8} סיבובים מלאים (שווה ערך ל-14\tfrac{1}{4} מסיבוב מלא), ו-Qubit 2 ב-208\tfrac{20}{8} סיבובים מלאים (שווה ערך ל-12\tfrac{1}{2} מסיבוב מלא).

2.5 תרגיל: QFT​

(1) מממש QFT של 4 qubits.

##your code goes here##

(2) החל QFT על ∣14⟩|14\rangle, סמלץ ושרטט את וקטור המצב באמצעות כדור בלוך.

##your code goes here##

פתרון התרגיל: QFT​

(1)

qr = QuantumRegister(4)
cr = ClassicalRegister(4)
qc = QuantumCircuit(qr, cr)

qc.h(3)
qc.cp(pi / 2, 2, 3)
qc.cp(pi / 4, 1, 3)
qc.cp(pi / 8, 0, 3)

qc.h(2)
qc.cp(pi / 2, 1, 2)
qc.cp(pi / 4, 0, 2)

qc.h(1)
qc.cp(pi / 2, 0, 1)

qc.h(0)

qc.swap(0, 3)
qc.swap(1, 2)

qc.draw(output="mpl")

Output of the previous code cell

(2)

bin(14)
'0b1110'
qc = QuantumCircuit(4)

qc.x(1)
qc.x(2)
qc.x(3)
qc.draw("mpl")

Output of the previous code cell

qc.h(3)
qc.cp(pi / 2, 2, 3)
qc.cp(pi / 4, 1, 3)
qc.cp(pi / 8, 0, 3)

qc.h(2)
qc.cp(pi / 2, 1, 2)
qc.cp(pi / 4, 0, 2)

qc.h(1)
qc.cp(pi / 2, 0, 1)
qc.h(0)

qc.swap(0, 3)
qc.swap(1, 2)

qc.draw(output="mpl")

Output of the previous code cell

statevector = Statevector(qc)
plot_bloch_multivector(statevector)

Output of the previous code cell

3. יסודות אומדן הפאזה הקוונטי (QPE)​

בהינתן פעולה יוניטרית UU, אלגוריתם QPE מעריך את θ\theta ב-U∣ψ⟩=e2πiθ∣ψ⟩U\vert\psi \rangle =e^{\boldsymbol{2\pi i} \theta }|\psi \rangle. מכיוון ש-UU יוניטרי, לכל ערכי העצם שלו יש נורמה של 1.

3.1 הליך​

1. הגדרה​

∣ψ⟩\vert\psi\rangle נמצא בקבוצה אחת של רשמי qubit. קבוצה נוספת של nn qubit יוצרת את רשם הספירה, שבו נאחסן את הערך 2nθ2^n\theta:

∣ψ0⟩=∣0⟩⊗n∣ψ⟩|\psi_0\rangle = \lvert 0 \rangle^{\otimes n} \lvert \psi \rangle

2. סופרפוזיציה​

מחילים פעולת Gate הדאמרד nn-סיבית H⊗nH^{\otimes n} על רשם הספירה:

∣ψ1⟩=12n2(∣0⟩+∣1⟩)⊗n∣ψ⟩|\psi_1\rangle = {\frac {1}{2^{\frac {n}{2}}}}\left(|0\rangle +|1\rangle \right)^{\otimes n} \lvert \psi \rangle

3. פעולות יוניטריות מבוקרות​

צריך להכיר את ה-CUCU היוניטרי המבוקר, שמחיל את האופרטור היוניטרי UU על רשם היעד רק אם סיבית הבקרה המתאימה היא ∣1⟩|1\rangle. מכיוון ש-UU הוא אופרטור יוניטרי עם וקטור עצם ∣ψ⟩|\psi\rangle כך ש-U∣ψ⟩=e2πiθ∣ψ⟩U|\psi \rangle =e^{\boldsymbol{2\pi i} \theta }|\psi \rangle, מתקיים:

U2j∣ψ⟩=U2j−1U∣ψ⟩=U2j−1e2πiθ∣ψ⟩=⋯=e2πi2jθ∣ψ⟩U^{2^{j}}|\psi \rangle =U^{2^{j}-1}U|\psi \rangle =U^{2^{j}-1}e^{2\pi i\theta }|\psi \rangle =\cdots =e^{2\pi i2^{j}\theta }|\psi \rangle

3.2 דוגמה: QPE עם T-gate​

בואו נשתמש ב-Gate מסוג TT כדוגמה ל-QPE ונעריך את הפאזה θ\theta שלו.

T∣1⟩=(100eiπ4)(01)=eiπ4∣1⟩T|1\rangle = \begin{pmatrix} 1 & 0\\ 0 & e^\frac{i\pi}{4}\\ \end{pmatrix} \begin{pmatrix} 0\\ 1\\ \end{pmatrix} = e^\frac{i\pi}{4}|1\rangle

אנחנו מצפים למצוא:

θ=18\theta = \frac{1}{8}

כאשר

T∣1⟩=e2iπθ∣1⟩T|1\rangle = e^{2i\pi\theta}|1\rangle

אנחנו מאתחלים את ∣ψ⟩=∣1⟩\vert\psi\rangle = \vert1\rangle של הווקטור העצמי של Gate מסוג TT על ידי החלת Gate מסוג XX:

qpe = QuantumCircuit(4, 3)
qpe.x(3)
qpe.draw(output="mpl")

Output of the previous code cell

לאחר מכן, מחילים Gate מסוג הדאמרד על qubit הספירה:

for qubit in range(3):
qpe.h(qubit)
qpe.draw(output="mpl")

Output of the previous code cell

מבצעים את הפעולות היוניטריות המבוקרות:

repetitions = 1
for counting_qubit in range(3):
for i in range(repetitions):
qpe.cp(pi / 4, counting_qubit, 3) # This is C-U
repetitions *= 2
qpe.draw(output="mpl")

Output of the previous code cell

מחילים את טרנספורמציית פורייה הקוונטית ההפוכה כדי להמיר את מצב רשם הספירה, ולאחר מכן מודדים את רשם הספירה:

from qiskit.circuit.library import QFT
# Apply inverse QFT
qpe.append(QFT(3, inverse=True), [0, 1, 2])
qpe.draw(output="mpl")

Output of the previous code cell

for n in range(3):
qpe.measure(n, n)
qpe.draw(output="mpl")

Output of the previous code cell

ניתן לדמות באמצעות הסימולטור Aer:

aer_sim = AerSimulator()
shots = 2048

pm = generate_preset_pass_manager(backend=aer_sim, optimization_level=1)
t_qpe = pm.run(qpe)

sampler = Sampler(mode=aer_sim)
job = sampler.run([t_qpe], shots=shots)
result = job.result()
answer = result[0].data.c.get_counts()

plot_histogram(answer)

Output of the previous code cell

אנחנו רואים שמקבלים תוצאה אחת (001) בוודאות, שמתורגמת לערך העשרוני: 1. עכשיו צריך לחלק את התוצאה (1) ב-2n2^n כדי לקבל את θ\theta:

θ=123=18\theta = \frac{1}{2^3} = \frac{1}{8}

האלגוריתם של שור מאפשר לנו לפרק מספר לגורמים על ידי בניית Circuit שבו θ\theta אינו ידוע ומציאת θ\theta.

3.3 תרגיל​

העריכו את θ=1/3\theta = 1/3 תוך שימוש ב-3 qubit לספירה ו-Qubit אחד עבור וקטור עצם.

P∣1⟩=eiλ∣1⟩P|1\rangle = e^{i\lambda}|1\rangle. מכיוון שאנחנו רוצים לממש U∣1⟩=e2πi13∣1⟩U|1\rangle = e^{2\pi i \tfrac{1}{3}}|1\rangle, צריך להגדיר λ=2π3\lambda = \tfrac{2 \pi}{3}.

##your code goes here##

פתרון התרגיל: θ=1/3\theta = 1/3​

# Create and set up circuit
qpe = QuantumCircuit(4, 3)

# Apply H-Gates to counting qubits:
for qubit in range(3):
qpe.h(qubit)

# Prepare our eigenstate |psi>:
qpe.x(3)

# Do the controlled-U operations:
angle = 2 * pi / 3
repetitions = 1
for counting_qubit in range(3):
for i in range(repetitions):
qpe.cp(angle, counting_qubit, 3)
repetitions *= 2

# Do the inverse QFT:
qpe.append(QFT(3, inverse=True), [0, 1, 2])

for n in range(3):
qpe.measure(n, n)

qpe.draw(output="mpl")

Output of the previous code cell

aer_sim = AerSimulator()
shots = 4096

pm = generate_preset_pass_manager(backend=aer_sim, optimization_level=1)
t_qpe = pm.run(qpe)

sampler = Sampler(mode=aer_sim)
job = sampler.run([t_qpe], shots=shots)
result = job.result()
answer = result[0].data.c.get_counts()

plot_histogram(answer)

Output of the previous code cell

4. הרצה באמצעות ה-Sampler primitive של IBM Quantum​

נבצע QPE באמצעות המכשיר הקוונטי האמיתי ונעקוב אחר 4 שלבים של תבניות Qiskit.

  1. מיפוי הבעיה לפורמט המותאם למחשב קוונטי

  2. אופטימיזציה של ה-Circuit

  3. הרצת ה-Circuit היעד

  4. עיבוד-המשך של התוצאות

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import Sampler
# Loading your IBM Quantum® account(s)

service = QiskitRuntimeService()

4.1 שלב 1: מיפוי הבעיה ל-Circuit ואופרטורים קוונטיים​

qpe = QuantumCircuit(4, 3)
qpe.x(3)
for qubit in range(3):
qpe.h(qubit)
repetitions = 1
for counting_qubit in range(3):
for i in range(repetitions):
qpe.cp(pi / 4, counting_qubit, 3) # This is C-U
repetitions *= 2
qpe.append(QFT(3, inverse=True), [0, 1, 2])
for n in range(3):
qpe.measure(n, n)
qpe.draw(output="mpl")

Output of the previous code cell

backend = service.least_busy(simulator=False, operational=True, min_num_qubits=4)

print(backend)
<IBMBackend('ibm_strasbourg')>

4.2 שלב 2: אופטימיזציה לחומרת היעד​

# Transpile the circuit into basis gates executable on the hardware
pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
qc_compiled = pm.run(qpe)

qc_compiled.draw("mpl", idle_wires=False)

Output of the previous code cell

4.3 שלב 3: הרצה על חומרת היעד​

real_sampler = Sampler(mode=backend)
job = real_sampler.run([qc_compiled], shots=1024)
job_id = job.job_id()
print("job id:", job_id)
job id: d13p4zb5z6q00087ag00
job = service.job(job_id) # Input your job-id between the quotations
job.status()
'DONE'
result_real = job.result()
print(result_real)
PrimitiveResult([SamplerPubResult(data=DataBin(c=BitArray(<shape=(), num_shots=1024, num_bits=3>)), metadata={'circuit_metadata': {}})], metadata={'execution': {'execution_spans': ExecutionSpans([DoubleSliceSpan(<start='2025-06-09 22:39:00', stop='2025-06-09 22:39:00', size=1024>)])}, 'version': 2})

4.4 שלב 4: עיבוד-המשך של התוצאות​

from qiskit.visualization import plot_histogram

plot_histogram(result_real[0].data.c.get_counts())

Output of the previous code cell

# See the version of Qiskit
import qiskit

qiskit.__version__
'2.0.2'