Ton première expérience quantique
Introduction
Dans la vidéo suivante, Olivia Lanes te guide à travers le contenu de cette leçon. Tu peux aussi ouvrir la vidéo YouTube de cette leçon dans une fenêtre séparée.
À présent, tu as exécuté ton premier circuit quantique et appris les bases de l'informatique quantique : comment les états quantiques sont représentés, comment les gates agissent sur ces états, et comment les caractéristiques quantiques comme la superposition et l'enchevêtrement entrent en jeu. Il est maintenant temps de mettre tout cela en pratique et de résoudre ton premier problème sur un ordinateur quantique.
Nous explorerons le panorama plus large des problèmes adaptés au quantique dans une leçon ultérieure. Pour l'instant, nous nous concentrerons sur un problème dans le domaine de la simulation de la nature : utiliser un ordinateur quantique comme substitut plus propre et plus contrôlable d'un système quantique naturel. En fait, c'est la première application qu'envisageait Richard Feynman pour les ordinateurs quantiques dans les années 1980. Comme il l'a dit avec éloquence : « La nature n'est pas classique, bon sang, et si tu veux faire une simulation de la nature, tu ferais mieux de la rendre quantique... »
Dans cette leçon, nous suivrons ce principe pour simuler l'interaction entre deux spins, que tu peux imaginer comme de minuscules aimants. Selon le signe de leur interaction, ils pourraient préférer s'aligner et pointer dans la même direction, ou s'anti-aligner et pointer dans des directions opposées. Nous nous concentrerons sur ce dernier cas car il conduit souvent à un comportement plus intéressant — et plus difficile. Une fois que nous comprendrons ce petit système à deux qubits, nous montrerons comment les mêmes idées passent à l'échelle supérieure, permettant aux ordinateurs quantiques de tirer parti de leur mise à l'échelle exponentielle lors de la simulation de grands systèmes de spins.
Deux aimants en interaction
Pour ce problème, nous allons utiliser deux qubits, un pour chaque spin dans notre modèle. Chaque spin peut pointer vers le haut (état du qubit ), vers le bas (état du qubit ), ou être en superposition des deux états.
Si les spins ont une interaction antiferromagnétique, cela signifie qu'ils veulent s'anti-aligner, donc quand l'un est vers le haut, l'autre veut être vers le bas, et vice-versa.
Suppose maintenant qu'il y a également un champ magnétique pointant de gauche à droite dans notre système. Comme ce champ pointe dans une direction transversale par rapport à la direction habituelle haut-bas des spins, il est appelé champ transverse. Ce champ peut retourner les spins, ce qui fait que la configuration d'énergie minimale est une superposition spécifique d'arrangements de spins haut-bas plutôt qu'un seul motif de spin défini.
Nous pouvons décrire tous ces effets à l'aide d'un objet mathématique appelé Hamiltonien. Le Hamiltonien nous indique l'énergie du système pour un arrangement donné de spins :
où est un coefficient contrôlant la force de l'interaction entre les spins et est un coefficient pour la force du champ magnétique externe. récompense ou pénalise les spins selon qu'ils sont alignés ou anti-alignés, et et représentent l'effet de retournement de spin du champ magnétique.
En physique, les systèmes ont tendance à se stabiliser dans l'état d'énergie la plus basse possible, appelé l'état fondamental. Trouver cet état d'énergie minimale est un problème courant, mais il nécessite des techniques d'optimisation qui dépassent le cadre de cette leçon.
À la place, nous poserons une question plus simple : Si nous préparons les spins dans un état particulier, quelle est l'énergie de cet état ?
Pour répondre à cela, nous allons :
- Préparer les spins dans un état de notre choix
- Mesurer l'énergie de cet état à l'aide du Hamiltonien ci-dessus
C'est exactement le type de calcul qui apparaît à l'intérieur de plus grands algorithmes quantiques, comme les algorithmes variationnels, que tu pourras explorer dans des cours ultérieurs.
Implémentation avec Qiskit
Avant de se lancer dans l'écriture de code, nous avons besoin d'un peu de contexte. Lorsque nous exécutons un circuit quantique, nous terminons toujours par mesurer les qubits. Mais il existe deux types de questions différentes que nous pouvons vouloir poser sur le résultat de cette mesure : Parfois, nous voulons simplement savoir quel est l'état du qubit. D'autres fois, nous voulons savoir, étant donné l'état quantique, quelle est la valeur d'une grandeur physique, comme l'énergie ?
Dans Qiskit, ces deux types de questions sont gérés par deux outils différents, appelés primitives.
Sampler répond au premier type de question. Il exécute le circuit plusieurs fois et nous indique à quelle fréquence nous mesurons chaque résultat possible, comme 00, 01, 10 ou 11. Le résultat est un histogramme montrant la probabilité de chaque résultat de mesure.
Estimator répond au second type de question. Au lieu de nous donner un histogramme, il combine plusieurs mesures en coulisses pour calculer un seul nombre, comme l'énergie de l'état selon un Hamiltonien que nous fournissons.
Pour t'aider à comprendre quand et pourquoi nous utiliserions chacun de ces outils, nous allons parcourir deux workflows complets (appelés « Qiskit patterns ») appliqués au même système à deux qubits.
Workflow Qiskit patterns
Le workflow Qiskit patterns est un cadre général que nous utilisons pour résoudre des problèmes quantiques avec Qiskit. Il décompose une tâche d'informatique quantique en quatre étapes :
- Mapper le problème à un modèle pouvant être représenté par des circuits quantiques
- Optimiser le circuit pour l'exécuter sur un Backend spécifique
- Exécuter le circuit optimisé sur le Backend sélectionné
- Post-traiter les données de mesure brutes
Expérience 1 : utilise Sampler pour mesurer l'état
Mapper
En général, l'étape de mapping est celle où nous déterminons comment représenter un problème du monde réel en termes de qubits, d'opérateurs et de mesures. Dans de nombreuses applications, c'est la partie la plus délicate et la plus complexe du workflow — même des questions simples, comme « que représente chaque qubit ? » n'ont pas toujours des réponses directes.
Dans cette expérience, cependant, le mapping est délibérément simple. Chaque degré de liberté physique se mappe directement sur un seul qubit. Grâce à cette correspondance un-à-un, l'étape de mapping se réduit à choisir l'état quantique que nous voulons préparer et à écrire un circuit qui prépare et mesure cet état.
Ici, nous allons préparer un état de Bell intriqué, similaire à celui que nous avons créé dans la toute première leçon de ce cours :
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
# Import Qiskit primitives
from qiskit import QuantumCircuit
# Make state
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.x(1)
qc.z(0)
# Measure state
qc.measure_all()
# Draw circuit
qc.draw("mpl")
Optimiser
Avant d'exécuter notre circuit sur un ordinateur quantique (ou un simulateur si tu as épuisé ton temps gratuit sur de vrais ordinateurs quantiques pour le mois), nous devons le préparer pour l'exécution. Cette étape est appelée optimisation. (Remarque : cette utilisation du mot « optimisation » peut prêter à confusion. En informatique quantique, les problèmes d'optimisation font référence à une classe spécifique de problèmes. Ici, nous utilisons optimisation pour décrire une étape de préparation obligatoire que chaque circuit quantique traverse avant de pouvoir être exécuté efficacement sur le matériel.)
Pendant l'optimisation :
- Nous choisissons le Backend — soit un vrai ordinateur quantique, soit un simulateur.
- Nous assignons les qubits de notre circuit à des qubits physiques sur le dispositif.
- Nous réécrivons le circuit en utilisant uniquement les gates que l'ordinateur quantique peut réellement exécuter.
- Nous implémentons optionnellement des techniques d'atténuation et de suppression des erreurs pour réduire les effets du bruit.
Dans Qiskit, cela est géré automatiquement par le transpiler. Une fois que tu as choisi ton Backend, le transpiler fait tout le travail pour rendre ton circuit prêt à l'exécution, sans que tu aies à ajuster manuellement les gates ou les assignations de qubits. Le transpiler propose également différents niveaux d'optimisation, qui peuvent aider à réduire les erreurs si nécessaire. L'optimisation se fait par étapes appelées « passes ». Ainsi, cette optimisation sera gérée par le pass_manager dans le code ci-dessous. Pour en savoir plus sur les erreurs et l'atténuation des erreurs, voir le cours Quantum Computing in Practice d'Olivia Lanes.
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
## Load the Qiskit Runtime service
# QiskitRuntimeService.save_account(
# channel="ibm_quantum_platform",
# token="YOUR_TOKEN_HERE",
# overwrite=True,
# set_as_default=True,
# )
# service = QiskitRuntimeService(channel="ibm_quantum_platform")
# Or load saved credentials
service = QiskitRuntimeService()
# Use the least busy backend, or uncomment the loading of a specific backend like "ibm_brisbane".
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
# backend = service.backend("ibm_brisbane")
print(backend.name)
ibm_fez
# Transpile the circuit and optimize for running on the quantum computer selected
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
qc_isa.draw("mpl")
Exécuter
Nous sommes maintenant prêts à exécuter ! Nous allons charger Sampler, puis envoyer le job au Backend.
# Load the Runtime primitive and session
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(mode=backend)
Ou, si tu utilises un simulateur, tu peux décommenter et exécuter cette cellule à la place :
## Load the backend sampler
# from qiskit.primitives import BackendSamplerV2
## Load the Aer simulator and generate a noise model based on the currently-selected backend.
# from qiskit_aer import AerSimulator
# from qiskit_aer.noise import NoiseModel
# noise_model = NoiseModel.from_backend(backend)
## Define a simulator using Aer, and use it in Sampler.
# backend_sim = AerSimulator(noise_model=noise_model)
# sampler_sim = BackendSamplerV2(backend=backend_sim)
## Alternatively, load a fake backend with generic properties and define a simulator.
## backend_gen = GenericBackendV2(num_qubits=18)
## sampler_gen = BackendSamplerV2(backend=backend_gen)
job = sampler.run([qc_isa], shots=100)
# job = sampler_sim.run([qc_isa]) # uncomment if you want to run on a simulator
res = job.result()
counts = res[0].data.meas.get_counts()
Post-traitement
from qiskit.visualization import plot_histogram
print("counts = ", counts)
plot_histogram(counts)
counts = {'10': 49, '01': 50, '11': 1}
On constate que la majorité des comptages se trouvent soit dans 01 soit dans 10, ce qui signifie que lorsqu'un qubit était mesuré à 0, l'autre était à 1, et vice-versa. Cela est cohérent avec l'état de Bell que nous avons préparé.
Expérience 2 : utilise Estimator pour mesurer l'énergie
Maintenant que nous avons vu comment échantillonner un état quantique, utilisons Estimator pour calculer l'énergie de notre état de Bell .
Mapper
Pour rappel, l'énergie du système est déterminée par l'interaction entre les spins () et le champ magnétique externe (), comme le capture le Hamiltonien :
Chaque terme du Hamiltonien nous indique comment une certaine combinaison de spins contribue à l'énergie. Dans Qiskit, nous pouvons représenter ces termes comme des opérateurs de Pauli, qui sont simplement des étiquettes pour des actions simples sur les qubits :
- agit avec un sur les deux qubits.
- agit avec sur le qubit 0.
- agit avec sur le qubit 1.
Un SparsePauliOp dans Qiskit est un moyen de stocker une liste de ces opérateurs de Pauli avec leurs coefficients numériques. Ces opérateurs de Pauli sont les observables que nous voulons que l'ordinateur quantique mesure — les grandeurs qui nous informent sur le système. En utilisant Estimator, nous pouvons calculer la valeur moyenne de chaque observable sur notre état et les combiner selon les coefficients du Hamiltonien pour obtenir l'énergie totale.
# Import Qiskit primitives
from qiskit.quantum_info import SparsePauliOp
# Parameters
J = 1.0 # antiferromagnetic coupling (J<0)
hx = -0.5 # transverse field strength
# 1. Define the Hamiltonian H = J Z1 Z2 + hx (X1 + X2)
obs = SparsePauliOp.from_list([("ZZ", J), ("XI", hx), ("IX", hx)])
# Make state
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.x(1)
qc.z(0)
<qiskit.circuit.instructionset.InstructionSet at 0x1387ed630>
Remarque que nous avons omis la ligne qc.measure_all() dans notre code. C'est parce qu'avec Estimator, nous n'avons pas besoin de spécifier où mesurer dans le circuit. Nous lui indiquerons simplement quelles observables nous voulons estimer, et Qiskit s'occupe des mesures en coulisses.
Optimiser
L'étape d'optimisation se déroule comme précédemment, avec en plus la vérification que nos observables sont également écrites d'une façon que l'ordinateur quantique peut comprendre.
# Transpile the circuit and optimize for running on the quantum computer selected
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
qc_isa.draw("mpl")
Exécuter
Dans l'étape d'exécution, nous allons charger Estimator, puis envoyer le circuit ainsi que la liste des observables que nous voulons estimer à l'ordinateur quantique.
# Load the Runtime primitive and session
from qiskit_ibm_runtime import EstimatorV2 as Estimator
estimator = Estimator(mode=backend)
# Load the backend sampler
# noise_model = NoiseModel.from_backend(backend)
# Use Aer simulator in Estimator
# estimator_sim = BackendEstimatorV2(backend=backend_sim)
# Alternatively, load a fake backend with generic properties and define a simulator.
# backend_gen = GenericBackendV2(num_qubits=18)
# estimator_gen = BackendEstimatorV2(backend=backend_gen)
pubs = [(qc_isa, obs_isa)]
job = estimator.run([[qc_isa, obs_isa]])
res = job.result()
# Uncomment lines below to run the job on the Aer simulator with noise model from real backend
# job = estimator_sim.run([[qc_isa,obs_isa]])
# res=job.result()
Post-traitement
Enfin, dans l'étape de post-traitement, nous affichons simplement l'énergie calculée en coulisses par Estimator.
print(res[0].data.evs)
-0.9934112021453058
C'est l'énergie de notre état !
Conclusion
Dans cette leçon, nous avons appris à préparer un état quantique simple à deux qubits représentant deux spins en interaction. Nous avons vu comment utiliser Sampler pour observer la distribution des résultats de mesure et comment utiliser Estimator pour calculer l'énergie de l'état selon le Hamiltonien. Au fil du chemin, nous avons vu comment le Hamiltonien encode les interactions entre les spins et les effets d'un champ externe, et comment différents états peuvent avoir des énergies différentes.
Extension à de nombreux spins
Jusqu'à présent, nous n'avons examiné que deux spins, ce qui est assez simple à analyser à la main. Dans les systèmes physiques réels, comme dans un aimant ou d'autres matériaux complexes, il y a souvent de nombreux spins en interaction. Lorsque le nombre de spins augmente, le Hamiltonien devient plus complexe et trouver l'état d'énergie minimale devient beaucoup plus difficile. C'est là que les ordinateurs quantiques peuvent aider : en préparant différents états et en estimant leurs énergies, nous pouvons explorer des configurations à basse énergie plus efficacement que les ordinateurs classiques pour les grands systèmes.
Une extension naturelle de cette expérience serait d'augmenter le nombre de qubits pour représenter plus de spins et d'ajuster la façon dont les spins sont préparés pour essayer de trouver l'état d'énergie minimale. Cette approche est l'essence des méthodes variationnelles, dont tu peux apprendre davantage dans le cours Variational Quantum Algorithms.
Il existe également d'autres approches quantiques pour étudier les énergies de l'état fondamental qui vont au-delà des techniques variationnelles. Ces méthodes ne sont pas couvertes ici, mais sont présentées dans le cours Quantum Diagonalization Algorithms si tu souhaites en apprendre davantage.
Objectif d'apprentissage
Reviens au début de l'Expérience 2 et réessaie avec un état de superposition différent. Peux-tu trouver un état avec une énergie encore plus basse que celui que nous avons utilisé ?