סימולציה של מודל Ising עם בעיטות על 127 qubit
במדריך הזה נשתמש בחבילה pauli-prop כדי לסמלץ בצורה קלאסית את הדינמיקה בזמן של מודל Ising עם בעיטות על 127 qubit ברשת heavy-hex, ולקרב את המגנטיזציה של אתר בודד, . ההמילטוניאן שבו נתמקד הוא:
כאשר מתאר את הצימוד בין ספינים שכנים, , ו- הוא השדה הרוחבי הגלובלי. פירוק Trotter מסדר ראשון של האופרטור המתפתח בזמן ימומש כמעגל קוונטי, , על פני צעדי Trotter. קבוע הצימוד, , יקבע ל- כך ש- הוא Clifford בכל פעם ש-.
תהליך עבודה:
-
יוצרים מעגלים קוונטיים שמממשים את מודל Ising בשיטת Trotter
- משנים את בין נקודות Clifford, ו-
-
בוחרים אתר באמצע הרשת (qubit ) ומעריכים את המגנטיזציה אחרי צעדי Trotter עבור כל מעגל
-
מתבוננים במגנטיזציה שיורדת מ- ל- כש- עובר מנקודת Clifford אחת לאחרת
יצירת מעגלים
קודם כול נשתמש ב-FakeSherbrooke מתוך qiskit-ibm-runtime כדי לקבל את אינדקסי הקשתות של מפת הצימוד של QPU מסוג Eagle עם 127 qubit. אחרי שיש לנו את אינדקסי הקשתות, ניצור את מעגלי Trotter עבור הערכים השונים של שאנחנו רוצים לסמלץ. המעגלים ימממשו פירוק 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
בשלב הבא נגדיר את האובזרבבל, , שאנחנו רוצים למדוד. במקרה הזה אנחנו מעריכים את .
כדי לחקור את המגנטיזציה בין נקודות Clifford, אנחנו מקדמים את בקירוב אל תחילת המעגל, , וכך מקבלים אובזרבבל חדש, .
במהלך הקידום, מספר האיברים באובזרבבל המתפתח גדל אקספוננציאלית במספר השערים, ולכן בדרך כלל צריך להגביל את הגודל שאליו הוא יכול לגדול. כאן אנחנו מגבילים את מספר האיברים ב- ל- וקוטעים איברים עם מקדמים קטנים מ-. קטיעת איברים גורמת לשגיאה מסוימת.
אחרי שיש לנו את , אפשר להעריך בקלות את ערך התצפית, , על ידי סכימת המקדמים של האיברים האלכסוניים ב- (איברים שמורכבים רק מ-I או Z בכל ה-qubit).
אנחנו מגדירים frame='h' כדי לציין שאנחנו רוצים לפתח את האובזרבבל במסגרת Heisenberg (). משתמשים ב-frame=s להתפתחות Schrödinger ().
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
הדמיה
לבסוף, נשרטט את המגנטיזציה כפונקציה של . כש-, המעגל לא משפיע על המצב ההתחלתי בבסיס החישובי, ואנחנו יודעים ש-. ככל ש- מתרחק מ-, המגנטיזציה דועכת באופן מונוטוני עד ש- מגיע לזווית ה-Clifford הבאה, , והמגנטיזציה מתכנסת ל-.
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>]
