Aller au contenu principal
Ce projet est en phase bêta. Tu as trouvé un bug ? Ouvrir un ticket GitHub. Une question ou une idée ? Pose ta question dans Discussions — tes retours sont les bienvenus !
Quelle est la qualité de la traduction sur cette page ?

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, ⟨Z62⟩\langle Z_{62} \rangle. L'hamiltonien considéré est :

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

où J>0J>0 décrit le couplage des spins plus proches voisins, i<ji<j, et hh 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, UU, sur 2020 pas de Trotter. La constante de couplage, JJ, sera fixée à J=−π2J=-\frac{\pi}{2} de sorte que UU soit de Clifford chaque fois que hmod  π2=0h\mod\frac{\pi}{2}=0.

Flux de travail :

  • Créer des Circuits quantiques implémentant le modèle d'Ising trotterisé

    • Faire varier hh entre les points de Clifford, 0.00.0 et π2\frac{\pi}{2}
  • Choisir un site au milieu du réseau (qubit 6262) et estimer l'aimantation après 2020 pas de Trotter pour chaque Circuit

  • Observer la décroissance de l'aimantation de 1.01.0 à 0.00.0 lorsque hh 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 hh 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, OO, que nous voulons mesurer. Dans ce cas, nous estimons ⟨Z62⟩\langle Z_{62} \rangle.

Pour étudier l'aimantation entre les points de Clifford, nous propageons approximativement OO jusqu'au début du Circuit, UU, ce qui donne une nouvelle observable, O′≈U†OUO^\prime \approx U^{\dagger}OU.

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 O′O^\prime à 10510^5 et tronquons les termes dont les coefficients sont inférieurs à 10−510^{-5}. La troncature des termes entraîne une certaine erreur. Une fois que nous avons O′O^\prime, nous pouvons facilement estimer la valeur moyenne, ⟨0∣U†OU∣0⟩=⟨0∣O′∣0⟩\langle0|U^{\dagger}OU|0\rangle = \langle0|O^\prime|0\rangle, en sommant les coefficients des termes diagonaux de O′O^\prime (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 (U†OUU^{\dagger}OU). Utilise frame=s pour l'évolution de 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

Visualiser​

Enfin, nous traçons l'aimantation en fonction de hh. Lorsque h=0h=0, le Circuit n'affecte pas l'état initial dans la base de calcul, et nous savons que ⟨0∣O∣0⟩=1.0\langle0|O|0\rangle = 1.0. À mesure que hh s'éloigne de 00, l'aimantation décroît de façon monotone jusqu'à ce que hh atteigne l'angle de Clifford suivant, π2\frac{\pi}{2}, et que l'aimantation converge vers 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