Simuler un modèle d'Ising avec kicks à 127 qubits
Dans ce guide, tu utilises le package pauli-prop pour simuler classiquement la dynamique temporelle d'un modèle d'Ising avec kicks à 127 qubits sur un réseau heavy-hex et approximer l'aimantation d'un seul site, . L'hamiltonien considéré est :
où décrit le couplage des spins plus proches voisins, , et est le champ transverse global. Une décomposition de Trotter du premier ordre de l'opérateur évolué dans le temps sera implémentée sous forme de Circuit quantique, , sur pas de Trotter. La constante de couplage, , sera fixée à de sorte que soit de Clifford chaque fois que .
Flux de travail :
-
Créer des Circuits quantiques implémentant le modèle d'Ising trotterisé
- Faire varier entre les points de Clifford, et
-
Choisir un site au milieu du réseau (qubit ) et estimer l'aimantation après pas de Trotter pour chaque Circuit
-
Observer la décroissance de l'aimantation de à lorsque passe d'un point de Clifford à un autre
Créer les Circuits
D'abord, nous utilisons FakeSherbrooke de qiskit-ibm-runtime pour obtenir les indices d'arêtes de la carte de couplage du QPU Eagle à 127 qubits. Une fois les indices d'arêtes obtenus, nous créons les Circuits de Trotter pour les différentes valeurs de que nous voulons simuler. Les Circuits implémenteront une trotterisation du premier ordre de l'hamiltonien avec 20 pas de Trotter et 5420 portes.
# 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)
Simuler la dynamique temporelle avec la propagation de Pauli
Ensuite, nous spécifions l'observable, , que nous voulons mesurer. Dans ce cas, nous estimons .
Pour étudier l'aimantation entre les points de Clifford, nous propageons approximativement jusqu'au début du Circuit, , ce qui donne une nouvelle observable, .
Pendant la propagation, le nombre de termes de l'observable évoluée croît exponentiellement avec le nombre de portes ; il est donc généralement nécessaire de limiter sa taille. Ici, nous limitons le nombre de termes de à et tronquons les termes dont les coefficients sont inférieurs à . La troncature des termes entraîne une certaine erreur.
Une fois que nous avons , nous pouvons facilement estimer la valeur moyenne, , en sommant les coefficients des termes diagonaux de (termes constitués uniquement de I ou Z sur tous les qubits).
Nous définissons frame='h' pour indiquer que nous voulons faire évoluer l'observable dans le cadre de Heisenberg (). Utilise frame=s pour l'évolution de 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
Visualiser
Enfin, nous traçons l'aimantation en fonction de . Lorsque , le Circuit n'affecte pas l'état initial dans la base de calcul, et nous savons que . À mesure que s'éloigne de , l'aimantation décroît de façon monotone jusqu'à ce que atteigne l'angle de Clifford suivant, , et que l'aimantation converge vers .
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>]
