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

סימולציה של מודל Ising עם בעיטות על 127 qubit

במדריך הזה נשתמש בחבילה pauli-prop כדי לסמלץ בצורה קלאסית את הדינמיקה בזמן של מודל Ising עם בעיטות על 127 qubit ברשת heavy-hex, ולקרב את המגנטיזציה של אתר בודד, ⟨Z62⟩\langle Z_{62} \rangle. ההמילטוניאן שבו נתמקד הוא:

H=−J∑⟨i,j⟩ZiZj+h∑iXiH = -J\sum\limits_{\langle i,j \rangle} Z_iZ_j + h\sum\limits_iX_i

כאשר J>0J>0 מתאר את הצימוד בין ספינים שכנים, i<ji<j, ו-hh הוא השדה הרוחבי הגלובלי. פירוק Trotter מסדר ראשון של האופרטור המתפתח בזמן ימומש כמעגל קוונטי, UU, על פני 2020 צעדי Trotter. קבוע הצימוד, JJ, יקבע ל-J=−π2J=-\frac{\pi}{2} כך ש-UU הוא Clifford בכל פעם ש-hmod  π2=0h\mod\frac{\pi}{2}=0.

תהליך עבודה:

  • יוצרים מעגלים קוונטיים שמממשים את מודל Ising בשיטת Trotter

    • משנים את hh בין נקודות Clifford, 0.00.0 ו-π2\frac{\pi}{2}
  • בוחרים אתר באמצע הרשת (qubit 6262) ומעריכים את המגנטיזציה אחרי 2020 צעדי Trotter עבור כל מעגל

  • מתבוננים במגנטיזציה שיורדת מ-1.01.0 ל-0.00.0 כש-hh עובר מנקודת Clifford אחת לאחרת

יצירת מעגלים​

קודם כול נשתמש ב-FakeSherbrooke מתוך qiskit-ibm-runtime כדי לקבל את אינדקסי הקשתות של מפת הצימוד של QPU מסוג Eagle עם 127 qubit. אחרי שיש לנו את אינדקסי הקשתות, ניצור את מעגלי Trotter עבור הערכים השונים של hh שאנחנו רוצים לסמלץ. המעגלים ימממשו פירוק Trotter מסדר ראשון של ההמילטוניאן עם 20 צעדי Trotter ו-5420 שערים.

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

_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "pauli_prop": "pauli-prop", "qiskit": "qiskit", "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")
import numpy as np
from qiskit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

# Get the edges in the device coupling map
backend = FakeSherbrooke()
edges = backend.coupling_map.get_edges()

# Num Trotter steps
num_steps = 20

# Create Trotter circuits with varying global fields
hs = [i * np.pi / 32 for i in range(17)]
circuits = []
for h in hs:
circuit = QuantumCircuit(backend.num_qubits)
for _ in range(num_steps):
circuit.rx(h, [i for i in range(backend.num_qubits)])
for edge in edges:
circuit.rzz(-np.pi / 2, edge[0], edge[1])
circuits.append(circuit)

סימולציה של הדינמיקה בזמן באמצעות Pauli propagation​

בשלב הבא נגדיר את האובזרבבל, OO, שאנחנו רוצים למדוד. במקרה הזה אנחנו מעריכים את ⟨Z62⟩\langle Z_{62} \rangle.

כדי לחקור את המגנטיזציה בין נקודות Clifford, אנחנו מקדמים את OO בקירוב אל תחילת המעגל, UU, וכך מקבלים אובזרבבל חדש, O′≈U†OUO^\prime \approx U^{\dagger}OU.

במהלך הקידום, מספר האיברים באובזרבבל המתפתח גדל אקספוננציאלית במספר השערים, ולכן בדרך כלל צריך להגביל את הגודל שאליו הוא יכול לגדול. כאן אנחנו מגבילים את מספר האיברים ב-O′O^\prime ל-10510^5 וקוטעים איברים עם מקדמים קטנים מ-10−510^{-5}. קטיעת איברים גורמת לשגיאה מסוימת. אחרי שיש לנו את O′O^\prime, אפשר להעריך בקלות את ערך התצפית, ⟨0∣U†OU∣0⟩=⟨0∣O′∣0⟩\langle0|U^{\dagger}OU|0\rangle = \langle0|O^\prime|0\rangle, על ידי סכימת המקדמים של האיברים האלכסוניים ב-O′O^\prime (איברים שמורכבים רק מ-I או Z בכל ה-qubit).

אנחנו מגדירים frame='h' כדי לציין שאנחנו רוצים לפתח את האובזרבבל במסגרת Heisenberg ‏(U†OUU^{\dagger}OU). משתמשים ב-frame=s להתפתחות Schrödinger ‏(UOU†UOU^{\dagger}).

import time

from pauli_prop import propagate_through_circuit
from qiskit.quantum_info import Pauli, SparsePauliOp

# Z_62 observable
id_pauli = Pauli("I" * backend.num_qubits)
observable = SparsePauliOp(id_pauli.dot(Pauli("Z"), [62]))

# Estimate the single-site magnetization for varying magnetic fields
times = []
approx_evs = []
for circuit in circuits:
st = time.perf_counter()
propagated_obs = propagate_through_circuit(
observable, circuit, 100_000, 1e-5, frame="h"
)[0]
times.append(time.perf_counter() - st)
approx_evs.append(
float(
propagated_obs.coeffs[~propagated_obs.paulis.x.any(axis=1)].sum()
)
)
print(f"Finished {len(circuits)} simulations in {sum(times):.0f}s")
Finished 17 simulations in 494s

הדמיה​

לבסוף, נשרטט את המגנטיזציה כפונקציה של hh. כש-h=0h=0, המעגל לא משפיע על המצב ההתחלתי בבסיס החישובי, ואנחנו יודעים ש-⟨0∣O∣0⟩=1.0\langle0|O|0\rangle = 1.0. ככל ש-hh מתרחק מ-00, המגנטיזציה דועכת באופן מונוטוני עד ש-hh מגיע לזווית ה-Clifford הבאה, π2\frac{\pi}{2}, והמגנטיזציה מתכנסת ל-00.

import matplotlib.pyplot as plt

plt.xlabel(r"$R_x$ angle $\theta_h$")
plt.ylabel(r"$\langle Z_{62} \rangle$")
plt.plot(hs, approx_evs, marker="o")
[<matplotlib.lines.Line2D at 0x123f68b00>]

Output of the previous code cell