Dynamics Simulator - une Qiskit Function de Q-CTRL Fire Opal
Consulte la référence de l'API.
Les Qiskit Functions sont une fonctionnalité expérimentale disponible uniquement pour les utilisateurs des plans IBM Quantum® Premium, Flex et On-Prem (via l'API d'IBM Quantum Platform). Elles sont en préversion et susceptibles de changer.
Aperçu
Le Dynamics Simulator de Q-CTRL est une Qiskit Function d'application pour simuler l'évolution temporelle de modèles quantiques à plusieurs corps pris en charge sur le matériel IBM Quantum. Au lieu de construire toi-même des circuits quantiques, tu spécifies le modèle physique, l'état initial, les paramètres d'évolution temporelle et les observables à mesurer.
La fonction construit et exécute les circuits dynamiques nécessaires et applique le workflow d'optimisation et de suppression des erreurs de Fire Opal, adapté au matériel. Le résultat est une trace temporelle de valeurs d'espérance pour les observables que tu as demandées. Comme la fonction applique la suppression des erreurs automatiquement, tu peux exécuter des circuits à des profondeurs record et obtenir tout de même des signaux significatifs. Le Dynamics Simulator offre une précision de solution équivalente à celle des outils classiques de pointe existants et un avantage démontrable en vitesse.
Des tests en conditions réelles ont atteint un accord à moins de 1 % d'erreur quadratique moyenne (RMSE) par rapport aux simulations classiques par réseaux de tenseurs de plus haute résolution. Des tests indépendants issus de la communauté de recherche ont validé que l'ordinateur quantique reste précis, même au-delà des démonstrations initiales de Q-CTRL.
Benchmarks
Le nombre de sites détermine combien de qubits sont nécessaires, tandis que le nombre de pas de Trotter contrôle la profondeur des circuits d'évolution temporelle. Chaque site du réseau utilise deux qubits pour représenter les occupations de spin haut et de spin bas.
Ce workflow a été démontré pour des chaînes de 60 sites (120 qubits) avec 30 pas de Trotter, et pour des chaînes de 31 sites (62 qubits) avec 90 pas de Trotter. Le tableau ci-dessous montre les ressources de circuit et les temps d'exécution QPU issus des expériences rapportées, réalisées sur un appareil IBM® Heron r3 (ibm_boston) avec 20 000 shots par circuit.
| Taille du système | Pas de Trotter | Profondeur à deux qubits | Nombre de portes à deux qubits | Temps QPU | Temps QPU avec REM + DR |
|---|---|---|---|---|---|
| 10 sites (20 qubits) | 30 | 152 | 1 457 | 2 min 46 s | 4 min 25 s |
| 10 sites (20 qubits) | 60 | 302 | 2 897 | 5 min 36 s | 8 min 42 s |
| 10 sites (20 qubits) | 90 | 452 | 4 337 | 8 min 46 s | 13 min 26 s |
| 31 sites (62 qubits) | 30 | 152 | 4 649 | 2 min 46 s | 4 min 25 s |
| 31 sites (62 qubits) | 60 | 302 | 9 239 | 5 min 36 s | 8 min 42 s |
| 31 sites (62 qubits) | 90 | 452 | 13 829 | 8 min 46 s | 13 min 26 s |
| 60 sites (120 qubits) | 30 | 152 | 9 057 | 2 min 46 s | 4 min 25 s |
Pour un nombre fixe de pas de Trotter, la profondeur de circuit et le temps QPU rapportés restent les mêmes pour toutes les tailles de système testées, tandis que le nombre de portes à deux qubits augmente. Augmenter le nombre de pas produit des circuits plus profonds et nécessite plus de temps QPU.
Ici, le temps QPU est le temps d'exécution cumulé sur le matériel pour les circuits de simulation principaux. La dernière colonne inclut aussi le temps QPU de la caractérisation du bruit utilisée pour la mitigation des erreurs de lecture (REM) et la récupération de la décroissance (DR). Ce guide utilise un petit exemple unidimensionnel de Fermi-Hubbard pour montrer le workflow complet, de la définition du modèle au tracé de la dynamique mesurée.
Description de la fonction
La dynamique quantique décrit comment un système quantique change au cours du temps. L'étude de cette évolution t'aide à comprendre comment les particules se déplacent, comment les corrélations se développent et comment un système réagit à un changement de son état ou de son hamiltonien.
Le modèle de Fermi-Hubbard décrit des fermions qui se déplacent entre des sites d'un réseau et interagissent lorsqu'ils occupent le même site. La compétition entre le saut et les interactions en fait un modèle utile pour étudier les électrons fortement corrélés. Son évolution temporelle peut révéler comment le spin et la charge se propagent, et comment un système initialement ordonné se relaxe.
Modèle
Le Dynamics Simulator prend en charge une chaîne de Fermi-Hubbard unidimensionnelle avec des bords ouverts. Pour une chaîne de sites, l'hamiltonien est défini comme suit :
Ici, et créent et annihilent un fermion de spin au site . L'opérateur nombre mesure l'occupation de cette orbitale de spin.
Les entrées du modèle spécifient les coefficients suivants :
-
hopping_amplitude: , qui contrôle le saut entre les sites voisins et . -
on_site_interaction: , l'interaction entre les fermions de spin haut et de spin bas qui occupent le même site. -
chemical_potential: , le potentiel chimique local, qui entre dans l'hamiltonien avec un signe moins.
Fournis un scalaire pour utiliser le même coefficient sur toute la chaîne, ou une liste pour spécifier des coefficients pour des liaisons ou des sites individuels.
Dans des unités où , l'état initial évolue comme suit :
La fonction estime les valeurs d'espérance des observables que tu spécifies à des instants de simulation successifs.
Workflow
Le workflow de la fonction comprend les étapes suivantes :
-
Synthèse algorithmique : La fonction utilise l'hamiltonien et les paramètres de temps de simulation pour construire une séquence de Trotter-Suzuki optimisée, ce qui réduit la profondeur du circuit tout en tenant compte de la précision de la simulation.
-
Mappage adapté au matériel : La fonction mappe et route les circuits en utilisant la connectivité des qubits et les caractéristiques d'erreur du Backend IBM Quantum sélectionné.
-
Suppression des erreurs de la couche physique : Fire Opal intègre le découplage dynamique et des corrections au niveau des impulsions pour supprimer le bruit de l'environnement et la diaphonie pendant l'exécution sur le matériel.
La fonction gère ces étapes automatiquement et renvoie les valeurs d'espérance des observables demandées au cours du temps.
Tu définis le problème physique et les paramètres de simulation via les entrées de la fonction. L'interface actuelle prend en charge l'évolution temporelle de Trotter, où time_step définit la durée de chaque pas et step_count définit le nombre de pas.
Pour plus de détails, consulte l'aperçu du simulateur de dynamique Fire Opal et la référence de l'API simulate_dynamics.
Pour commencer
Trouve les informations d'accès à cette Qiskit Function dans le Qiskit Functions Catalog.
Ce guide montre comment charger le Dynamics Simulator et simuler une chaîne de Fermi-Hubbard de quatre sites. Le code suivant suppose que tu as déjà enregistré ta clé d'API IBM Quantum Platform et le CRN de ton instance dans ton environnement local.
Pour la configuration du compte et les instructions d'installation du client, consulte Premiers pas avec les Qiskit Functions.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "qctrlvisualizer": "qctrlvisualizer", "qiskit_ibm_catalog": "qiskit-ibm-catalog"}
_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")
from qiskit_ibm_catalog import QiskitFunctionsCatalog
catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# Access the Q-CTRL Dynamics Simulator Qiskit Function.
sim_qf = catalog.load("q-ctrl/dynamics-simulator")
# Check the list of backends you have access to
catalog.backends()
[<IBMBackend('ibm_boston')>,
<IBMBackend('ibm_fez')>,
<IBMBackend('ibm_kingston')>,
<IBMBackend('ibm_marrakesh')>,
<IBMBackend('ibm_miami')>,
<IBMBackend('ibm_phoenix')>,
<IBMBackend('ibm_pittsburgh')>]
# Select the backend you want to use
backend = catalog.backend("ibm_phoenix")
Exemple : simuler une chaîne de Fermi-Hubbard de quatre sites
Considère une chaîne de Fermi-Hubbard unidimensionnelle de quatre sites avec une amplitude de saut , sans interaction sur site et avec un potentiel chimique nul. Un seul fermion de spin haut commence au site 0 et évolue le long de la chaîne.
Ce petit problème garde l'attention sur le workflow du Dynamics Simulator :
-
Définis le modèle et la simulation.
-
Définis l'état initial et les observables.
-
Soumets le job Qiskit Function.
-
Récupère les valeurs moyennes.
-
Trace la dynamique.
1. Définir le problème
site_count = 4
model = {
"hopping_amplitude": 1.0,
"on_site_interaction": 0.0,
"chemical_potential": 0.0,
}
simulation = {
"time_step": 0.2,
"step_count": 8,
}
initial_state = "eeeu"
observables = [
{
"operators": [[["Nup", site]]],
"coefficients": [1.0],
}
for site in range(site_count)
]
shot_count = 2048
La liste d'observables mesure l'occupation de spin up
à chaque site. Les observables sont renvoyées dans le même ordre que celui dans lequel elles sont fournies.
2. Exécuter la simulation de la dynamique
Soumets le problème via la Qiskit Function. Le Qiskit Functions Catalog gère l'authentification IBM Quantum, donc tu ne transmets pas d'identifiants Fire Opal ou de fournisseur matériel distincts à sim_qf.run().
job = sim_qf.run(
model=model,
simulation=simulation,
observables=observables,
initial_state=initial_state,
shots=shot_count,
backend_name=backend.name,
)
print(job.job_id, job.status())
68202fad-6919-425d-8fd2-c1c649cd15b1 DONE
L'objet renvoyé est un job Qiskit Function. Tu peux conserver l'ID du job pour récupérer ou inspecter la charge de travail plus tard.
3. Récupérer le résultat
result = job.result()
print("Result keys:", sorted(result.keys()))
print("Warnings:", result.get("warnings", []))
Result keys: ['metadata', 'observable_expectation_values', 'observables', 'warnings']
Warnings: []
Convertis les valeurs moyennes des observables en tableau NumPy. Chaque ligne correspond à une observable et chaque colonne à un temps de simulation enregistré, à partir de . Pour cet exemple, les quatre lignes contiennent les occupations de spin up des sites 0 à 3.
import numpy as np
expectation_values = np.asarray(
result["observable_expectation_values"],
dtype=float,
)
print("Expectation-value array shape:", expectation_values.shape)
Expectation-value array shape: (4, 9)
4. Visualiser la dynamique
L'état initial contient un fermion de spin up et aucun fermion de spin down. Son évolution reste donc dans le sous-espace à une seule particule, dont les quatre états de base correspondent au fermion occupant les sites 0, 1, 2 et 3.
Dans ce sous-espace, l'hamiltonien relie les sites voisins avec une amplitude de saut . Pour les paramètres utilisés ici,
Diagonalise cette matrice avec NumPy et fais évoluer l'état initial aux mêmes temps que ceux renvoyés par le Dynamics Simulator. Le carré du module de chaque amplitude d'état donne l'occupation de spin up du site correspondant.
Ce calcul donne l'évolution hamiltonienne exacte. Les différences entre les estimations matérielles et cette référence peuvent inclure le pas de Trotter fini, les statistiques de mesure et les erreurs matérielles résiduelles.
times = np.arange(expectation_values.shape[1]) * simulation["time_step"]
# This reference is specific to a single spin-up fermion.
if (
len(initial_state) != site_count
or initial_state.count("u") != 1
or initial_state.count("e") != site_count - 1
):
raise ValueError(
"This reference requires one spin-up fermion and otherwise empty sites."
)
# Build the Hamiltonian in the single-particle subspace.
hamiltonian = -model["hopping_amplitude"] * (
np.eye(site_count, k=1) + np.eye(site_count, k=-1)
)
hamiltonian -= model["chemical_potential"] * np.eye(site_count)
# The rightmost character of initial_state corresponds to site 0.
initial_amplitudes = np.zeros(site_count, dtype=complex)
initial_site = initial_state[::-1].index("u")
initial_amplitudes[initial_site] = 1.0
# Evolve the initial state in the Hamiltonian eigenbasis.
energies, eigenvectors = np.linalg.eigh(hamiltonian)
initial_coefficients = eigenvectors.conj().T @ initial_amplitudes
phases = np.exp(-1j * np.outer(energies, times))
states = eigenvectors @ (initial_coefficients[:, None] * phases)
ideal_expectation_values = np.abs(states) ** 2
Trace un panneau par site. Les courbes pleines montrent la référence exacte aux temps enregistrés, et les marqueurs montrent les estimations matérielles renvoyées par le Dynamics Simulator.
import matplotlib.pyplot as plt
import qctrlvisualizer as qv
from qctrlvisualizer import QCTRL_STYLE_COLORS as colors
plt.style.use(qv.get_qctrl_style())
fig, ax = plt.subplots(figsize=(10, 6))
for site in range(len(expectation_values)):
site_color = colors[site % len(colors)]
ax.plot(
times,
ideal_expectation_values[site],
color=site_color,
linewidth=2,
label=f"Site {site}: exact reference",
)
ax.plot(
times,
expectation_values[site],
color=site_color,
linestyle="--",
linewidth=1.5,
marker="o",
markersize=5,
label=f"Site {site}: hardware estimate",
)
ax.set_xlim(times[0], times[-1])
ax.set_ylim(-0.05, 1.05)
ax.set_xlabel(r"Time (units of $\hbar/t_h$)")
ax.set_ylabel(r"$\langle n_{i\uparrow} \rangle$")
ax.set_title("Spin-up occupation dynamics")
ax.legend(
ncol=2,
fontsize=10,
loc="best",
)
fig.tight_layout()
plt.show()

À , l'occupation exacte de spin up vaut 1 au site 0 et 0 aux autres sites. Au fil de l'évolution du système, le saut répartit la probabilité de la particule le long de la chaîne. L'occupation du site 1 augmente en premier, suivie de l'augmentation de l'occupation des sites 2 et 3. Pour les paramètres de cet exemple, le dernier temps enregistré est . Les occupations exactes des sites 0 à 3 valent respectivement environ 0,026, 0,370, 0,392 et 0,211.
Les occupations exactes satisfont l'équation suivante à chaque instant, ce qui reflète la conservation du nombre de particules :
Les occupations individuelles des sites peuvent monter et descendre à mesure que la particule évolue dans la chaîne finie.
Récupérer les messages d'erreur
Si la charge de travail passe à l'état ERROR, appelle job.result() pour récupérer le message d'erreur. Tu peux aussi inspecter les logs de la fonction, s'ils sont disponibles.
print(job.status())
if job.status() == "ERROR":
print(job.result())
print(job.logs())
DONE
Parmi les problèmes courants de validation des entrées figurent un modèle ou une méthode de simulation non pris en charge, une chaîne d'état initial trop longue, des termes et coefficients d'observables qui ne correspondent pas, ou une observable qui référence un site en dehors de la chaîne d'état initial.
Obtenir de l'aide
Pour toute question sur le comportement du Dynamics Simulator ou de Fire Opal, consulte la documentation Q-CTRL ou contacte Q-CTRL.
Pour l'authentification Qiskit Functions, la gestion des jobs ou l'accès à IBM Quantum Platform, consulte la documentation Qiskit Functions.
Étapes suivantes
- Consulte la référence de l'API
simulate_dynamicspour les définitions du modèle, de la simulation, des observables, de la sortie et de la validation. - Essaie le tutoriel Dynamique de spin et de charge dans le modèle de Fermi-Hubbard.
- Lis la présentation du simulateur de dynamique Fire Opal pour plus de détails sur la trotterisation, le mappage adapté au matériel et la suppression d'erreurs de Fire Opal.
- Modifie les paramètres du modèle, l'état initial, le pas de temps, le nombre de pas et les observables pour étudier un autre problème de dynamique de Fermi-Hubbard à une dimension.