⚛️ Python Quantique avec Qiskit
Octobre 2025
Bienvenue dans cette introduction au calcul quantique avec Python. Nous allons utiliser la bibliothèque Qiskit pour créer des circuits quantiques simples, les exécuter et visualiser les résultats.
Le calcul quantique est une nouvelle manière de traiter l'information, reposant sur les qubits (quantum bits). Contrairement aux bits classiques, qui ne peuvent être que 0 ou 1, un qubit peut exister dans une superposition d'états : il est alors simultanément, en partie, dans l'état \( |0\rangle \) et \( |1\rangle \).
En informatique classique, l'information est codée à l'aide de bits prenant la valeur 0 ou 1.
En informatique quantique, l'information est codée dans des systèmes quantiques à deux niveaux, dont les deux états de base sont notés \( |0\rangle \) et \( |1\rangle \). Un qubit peut être uniquement dans \( |0\rangle \), uniquement dans \( |1\rangle \) ou dans une combinaison linéaire des deux, ce qui constitue la superposition.
C'est cette propriété qui permet aux ordinateurs quantiques d'explorer plusieurs possibilités en parallèle et d'ouvrir la voie à des algorithmes bien plus rapides pour certaines tâches que leurs équivalents classiques.
La porte Hadamard
En informatique quantique, une porte quantique est l'équivalent d'une porte logique classique, mais apliquée à des qubits. Parmi les plus importantes, la porte Hadamard (H) joue un rôle central : elle sert à créer une superposition équiprobable à partir d'un état de base.
1. Intuition
- Un bit classique est soit 0, soit 1.
- Un qubit, avant la mesure, peut être dans une combinaison de \( |0\rangle \) et \( |1\rangle \).
- La porte Hadamard prend un état de base et le transforme en superposition où les deux résultats sont possibles avec la même probabilité.
2. Forme mathématique
En notation matricielle, la porte Hadamard est définie par : $$H = \frac{1}{\sqrt{2}} \begin{pmatrix}1 & 1\\1 & -1\end{pmatrix}$$
3. Calculs
Cas \( |0\rangle \)
$$ |0\rangle = \begin{pmatrix}1 \\0 \end{pmatrix} $$
Application de H :
$$H |0\rangle = \frac{1}{\sqrt{2}} \begin{pmatrix}1 & 1\\1 & -1\end{pmatrix}\begin{pmatrix}1 \\0 \end{pmatrix} = \frac{1}{\sqrt{2}}\begin{pmatrix}1 \\1 \end{pmatrix}$$
Ce qui donne :
$$H |0\rangle = \frac{ \ |0\rangle + |1\rangle}{\sqrt{2}} $$
Cas \( |1\rangle \)
$$ |1\rangle = \begin{pmatrix}0 \\1 \end{pmatrix} $$
Application de H :
$$H |1\rangle = \frac{1}{\sqrt{2}} \begin{pmatrix}1 & 1\\1 & -1\end{pmatrix}\begin{pmatrix}0 \\1 \end{pmatrix} = \frac{1}{\sqrt{2}}\begin{pmatrix}1 \\-1 \end{pmatrix}$$
Ce qui donne :
$$H |1\rangle = \frac{ \ |0\rangle - |1\rangle}{\sqrt{2}} $$
La porte Hadamard est un outil pour préparer le terrain
avant d'appliquer d'autres portes (comme CNOT) afin de créer
des états intriqués ou de tester simultanément plusieurs cas dans un algorithme.
Circuit 1 : Circuit simple avec 1 qubit (sans mesure).
Dans ce premier circuit quantique, nous utilisons un seul qubit. En lui appliquant une porte Hadamard (H), on le place dans un état de superposition : il est à la fois dans l'état \( |0\rangle \) et \(|1\rangle \). Aucune mesure n'est effectuée.
from qiskit import QuantumCircuit
from qiskit.visualization import circuit_drawer
import matplotlib.pyplot as plt
# Circuit : 1 qubit
qc = QuantumCircuit(1)
# Application d'une porte Hadamard
qc.h(0)
# Affichage du circuit
print(qc.draw())
plt.show()
Circuit 2 : Circuit avec un qubit, un bit classique et une mesure.
Ce circuit quantique utilise une porte Hadamard (H) à un qubit initialisé à \( |0\rangle \), le mettant en superposition entre \( |0\rangle \) et \( |1\rangle \). Lors de la mesure (effectuée 1000 fois), on obtient environ 50 % de 0 et 50 % de 1, comme le montre le résultat de la mesure suivant : {'1': 498, '0': 502}.
Ce petit exemple montre l'un des principes fondamentaux du calcul quantique :
l'incertitude et la nature probabiliste des mesures.
from qiskit import QuantumCircuit, transpile
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram
import matplotlib.pyplot as plt
# Création d'un circuit avec 1 qubit et 1 bit classique
qc = QuantumCircuit(1, 1)
# Porte Hadamard : crée une superposition sur le qubit 0
qc.h(0)
qc.measure(0, 0) # Mesure du qubit 0
print(qc.draw()) # Affichage du circuit dans la console
# Initialisation du simulateur
simulator = AerSimulator()
# Exécution du circuit
compiled_circuit = transpile(qc, simulator)
simu = simulator.run(compiled_circuit, shots=1000)
result = simu.result()
# Récupérer les résultats
counts = result.get_counts()
print("Résultats de la mesure :", counts)
# Affichage des résultats
plot_histogram(counts)
plt.show()
La porte CNOT
1. Intuition
La porte CNOT (Controlled-NOT) est une porte à deux qubits :
- Un qubit contrôle,
- Un qubit cible.
Si le qubit contrôle vaut \( |1\rangle \), la porte applique une X (NOT) sur le qubit cible. Si le qubit contrôle vaut \( |0\rangle \), la cible reste inchangée.
C'est la porte de base pour créer de l'intrication (entanglement) quand on la combine avec une porte Hadamard sur le qubit contrôle.
Circuit 3 : Intrication quantique avec Hadamard et CNOT
Ce circuit illustre l'un des phénomènes les plus fascinants de la mécanique quantique : l'intrication. En appliquant une porte Hadamard (H) sur le premier qubit, nous le plaçons en superposition. Ensuite, la porte CNOT lie l'état du premier qubit au second, créant une corrélation parfaite entre eux.
A chaque exécution, les mesures peuvent donner 00 ou 11, mais jamais 01 ou 10. Ce lien persiste même si les qubits sont séparés physiquement, ce qui est au coeur de nombreuses applications comme la cryptographie quantique ou le calcul quantique distribué.
# Création d'un circuit avec 2 qubits et 2 bits classique
qc = QuantumCircuit(2, 2)
# Porte Hadamard sur le premier circuit
qc.h(0)
# Porte CNOT (intrication)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1]) # Mesure des deux qubits
# Affichage du circuit
print(qc.draw())
# Initialisation du simulateur
simulator = AerSimulator()
# Exécuter le circuit pour le simulateur
compiled_circuit = transpile(qc, simulator)
simu = simulator.run(compiled_circuit, shots=1000)
result = simu.result()
# Récupérer les résultats
counts = result.get_counts()
print("Résultats de la mesure :", counts)
...
Résultats de la mesure : {'00': 502, '11': 498}
algorithme de Deutsch-Jozsa
L'algorithme de Deutsch-Jozsa est l'un des premiers algorithmes quantiques. Il permet de répondre à une question simple :
Une fonction binaire est-elle constante (donne toujours le même résultat) ou équilibrée (donne parfois 0 et parfois 1).
En informatique classique, il faudrait tester deux entrées pour le savoir.
En informatique quantique, un seul calcul suffit grâce à la superposition des qubits.
1. Circuit de base
from qiskit import QuantumCircuit
qc = QuantumCircuit(2, 1)
# Préparation
qc.h(0)
qc.x(1)
qc.h(1)
# Oracle (boîte noire)
qc.cx(0, 1)
# Lecture
qc.h(0)
qc.measure(0, 0)
qc.draw('mpl')
Pour illustrer l'algorithme de Deutsch-Jozsa, on représente deux circuits différents selon la nature de l'oracle (la "boîte noire" qui encode la fonction). Dans le premier cas, l'oracle est constant et le résultat de la mesure est toujours 0. Dans le second cas, l'oracle équilibré et la mesure retourne toujours 1. Ces circuits montrent comment un calcul quantique permet de déterminer en une seule évaluation si la fonction est constante ou équilibrée, alors qu'en classique il faudrait deux évaluations.
Cas 1 - Fonction constante
Le circuit associé produit toujours la sortie 0 :
Résultat circuit constant : {'0': 1024}
backend = Aer.get_backend('qasm_simulator')
qc_constant = QuantumCircuit(2, 1)
qc_constant.x(1) # Préparation du second qubit en |1>
qc_constant.h([0, 1])
# Oracle constant : ne fait rien
qc_constant.h(0)
qc_constant.measure(0, 0)
# Transpile et exécution
tqc_constant = transpile(qc_constant, backend)
job_constant = backend.run(tqc_constant, shots=1024)
counts_constant = job_constant.result().get_counts()
print("Résultat circuit constant :", counts_constant)
qc_constant.draw('mpl')
plot_histogram(counts_constant)
cas 2 - Fonction équilibrée
Le circuit associé produit toujours la sortie 1 :
Résultat circuit équilibré : {'1': 1024}
backend = Aer.get_backend('qasm_simulator')
qc_balanced = QuantumCircuit(2, 1)
qc_balanced.x(1) # Préparation du second qubit en |1>
qc_balanced.h([0, 1])
qc_balanced.cx(0, 1) # Oracle équilibré
qc_balanced.h(0)
qc_balanced.measure(0, 0)
# Transpile et exécution
tqc_balanced = transpile(qc_balanced, backend)
job_balanced = backend.run(tqc_balanced, shots=1024)
counts_balanced = job_balanced.result().get_counts()
print("Résultat circuit équilibré :", counts_balanced)
qc_balanced.draw('mpl')
plot_histogram(counts_balanced)
Portes supplémentaires
La porte Ry(θ)
La porte Ry(θ) fait tourner l'état d'un qubit autour de l'axe y de la sphère de Bloch, d'un angle θ.
Intrication à 3 qubits
A suivre
🔬 À venir
Cette page sera enrichie avec d'autres circuits plus complexes, l'introduction à l'intrication (entanglement), et des applications concrètes du Python quantique.