Zasymuluj 127-kubitowy model Isinga z kopnięciami (kicked Ising)
W tym przewodniku używamy pakietu pauli-prop, aby klasycznie zasymulować dynamikę czasową 127-kubitowego modelu Isinga z kopnięciami (kicked Ising) na sieci heavy-hex i przybliżyć magnetyzację pojedynczego węzła, . Rozważany hamiltonian ma postać:
gdzie opisuje sprzężenie spinów najbliższych sąsiadów, , a jest globalnym polem poprzecznym. Rozkład Trottera pierwszego rzędu operatora ewolucji w czasie zostanie zaimplementowany jako obwód kwantowy, , o krokach Trottera. Stała sprzężenia, , zostanie ustalona na , tak że jest cliffordowskie zawsze, gdy .
Przepływ pracy:
-
Utwórz obwody kwantowe implementujące model Isinga metodą Trottera
- Zmieniaj między punktami Clifforda, i
-
Wybierz węzeł w środku sieci (kubit ) i oszacuj magnetyzację po krokach Trottera dla każdego obwodu
-
Zaobserwuj spadek magnetyzacji z do , gdy przechodzi z jednego punktu Clifforda do drugiego
Utwórz obwody
Najpierw używamy FakeSherbrooke z qiskit-ibm-runtime, aby uzyskać indeksy krawędzi mapy sprzężeń 127-kubitowego QPU Eagle. Gdy mamy indeksy krawędzi, tworzymy obwody Trottera dla różnych wartości , które chcemy zasymulować. Obwody zaimplementują rozkład Trottera pierwszego rzędu hamiltonianu z użyciem 20 kroków Trottera i 5420 bramek.
# 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)
Zasymuluj dynamikę czasową za pomocą propagacji Pauliego
Następnie określamy obserwablę, , którą chcemy zmierzyć. W tym przypadku szacujemy .
Aby zbadać magnetyzację między punktami Clifforda, w przybliżeniu propagujemy na początek obwodu, , otrzymując nową obserwablę, .
Podczas propagacji liczba wyrazów w ewoluowanej obserwablej rośnie wykładniczo wraz z liczbą bramek, więc zwykle trzeba ograniczyć, jak bardzo może urosnąć. Tutaj ograniczamy liczbę wyrazów w do i obcinamy wyrazy o współczynnikach mniejszych niż . Obcinanie wyrazów powoduje pewien błąd.
Gdy mamy , możemy łatwo oszacować wartość oczekiwaną, , sumując współczynniki wyrazów diagonalnych w (wyrazów składających się wyłącznie z I lub Z na wszystkich kubitach).
Ustawiamy frame='h', aby określić, że chcemy ewoluować obserwablę w ujęciu Heisenberga (). Użyj frame=s dla ewolucji w ujęciu Schrödingera ().
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
Wizualizacja
Na koniec rysujemy magnetyzację jako funkcję . Gdy , obwód nie wpływa na stan początkowy w bazie obliczeniowej i wiemy, że . W miarę oddalania się od magnetyzacja maleje monotonicznie, aż osiągnie kolejny kąt Clifforda, , a magnetyzacja zbiegnie do .
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>]
