Bruit, décohérence et canaux quantiques & Correction d'erreur — bases
Comprendre le bruit quantique (T1, T2, dépolarisation), les canaux de Kraus et les fondements de la correction d'erreur — sans prérequis mathématiques, avec du code Q# et Qiskit.
Bruit, décohérence et canaux quantiques
Pourquoi les qubits font des erreurs
Un qubit, c’est un système physique extrêmement fragile. En théorie, il maintient sa superposition indéfiniment. En pratique, il interagit constamment avec son environnement — atomes voisins, champs électromagnétiques parasites, vibrations thermiques. Ces interactions corrompent l’état du qubit de manière incontrôlée. C’est le bruit quantique.
Analogie : Imagine une toupie qui tourne parfaitement sur une table lisse. C’est ton qubit idéal. Maintenant, pose cette toupie sur une table bancale, avec des courants d’air et des vibrations — elle va ralentir, osciller, et finir par tomber. C’est exactement ce qui arrive à un qubit réel : l’environnement le « secoue » jusqu’à ce qu’il perde son information.
T1 — Relaxation (perte d’énergie)
Le temps T1 mesure combien de temps un qubit excité (|1⟩) met à retomber spontanément vers |0⟩. C’est une perte d’énergie irréversible — le qubit « dégringole » vers son état fondamental.
Analogie : Une balle posée en haut d’une colline. Même sans la toucher, elle finira par rouler vers le bas à cause des vibrations du sol. T1, c’est le temps moyen avant qu’elle atteigne le fond. Plus T1 est long, plus ton qubit tient longtemps en
|1⟩.
Valeurs typiques : sur les processeurs supraconducteurs actuels (IBM, Google), T1 est de l’ordre de 100 à 300 microsecondes. Ça paraît court, mais une porte quantique prend environ 20 à 50 nanosecondes — tu as donc le temps d’exécuter quelques milliers de portes avant que la relaxation ne corrompe sérieusement ton qubit.
T2 — Déphasage (perte de phase)
Le temps T2 mesure combien de temps le qubit conserve sa relation de phase entre |0⟩ et |1⟩. En superposition α|0⟩ + β|1⟩, la phase relative entre α et β est essentielle pour les interférences quantiques. Le déphasage la brouille.
Analogie : Imagine deux horloges parfaitement synchronisées. Avec le temps, l’une dérive légèrement — elles ne marquent plus la même heure. Le déphasage, c’est cette dérive : les amplitudes du qubit sont intactes, mais la relation de phase est perdue. Sans phase cohérente, plus d’interférence, plus de calcul quantique utile.
Règle importante : T2 ≤ 2 × T1 toujours. Le déphasage est au moins aussi rapide que la relaxation, souvent plus rapide. En pratique, T2 est souvent entre 50 % et 100 % de T1.
Les principaux canaux de bruit
Un canal quantique décrit mathématiquement comment le bruit transforme l’état d’un qubit. C’est l’équivalent d’une « fonction de corruption ». Voici les quatre canaux fondamentaux :
| Canal | Ce qui se passe | Analogie | Opérateurs de Kraus |
|---|---|---|---|
| Bit-flip | |0⟩ ↔ |1⟩ avec probabilité p | Un interrupteur qui se déclenche tout seul — la lumière passe de ON à OFF au hasard. | E₀ = √(1-p) · I, E₁ = √p · X |
| Phase-flip | La phase s’inverse (|1⟩ acquiert un signe −) avec probabilité p | L’horloge saute soudainement de 12h à 6h — l’aiguille pointe dans la direction opposée. | E₀ = √(1-p) · I, E₁ = √p · Z |
| Dépolarisation | Le qubit est remplacé par un état complètement aléatoire avec probabilité p | Un dé qui « oublie » quelle face était en haut — il se remet dans une position totalement aléatoire. | E₀ = √(1-3p/4) · I, E₁ = √(p/4) · X, E₂ = √(p/4) · Y, E₃ = √(p/4) · Z |
| Amplitude damping | |1⟩ → |0⟩ avec probabilité γ (modélise T1) | La balle qui roule du haut de la colline — elle perd son énergie progressivement. | E₀ = |0⟩⟨0| + √(1-γ) · |1⟩⟨1|, E₁ = √γ · |0⟩⟨1| |
Opérateurs de Kraus — des « delegates de bruit »
En jour 20-21, on a vu les opérateurs de Kraus dans le contexte des états mixtes. Ici, on les applique concrètement au bruit. Un canal quantique transforme la matrice densité ρ en :
ρ' = Σₖ Eₖ ρ Eₖ†
Chaque opérateur Eₖ représente un scénario possible de ce que l’environnement fait au qubit. La contrainte Σₖ Eₖ† Eₖ = I garantit que les probabilités totales restent à 1.
Analogie C# : Pense aux opérateurs de Kraus comme une liste de
Func<Matrix, Matrix>. Chaque delegate transforme l’état du qubit d’une manière différente (flip, phase, rien…). Le canal applique chaque delegate avec une certaine probabilité et combine les résultats. C’est du pattern matching probabiliste sur l’état quantique.
Simulation de bruit avec Qiskit Aer
Voici comment simuler un circuit bruité avec Qiskit :
from qiskit import QuantumCircuit, transpile
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel, depolarizing_error
# Créer un circuit simple : superposition + mesure
qc = QuantumCircuit(1, 1)
qc.h(0) # Mettre le qubit en superposition |+⟩
qc.measure(0, 0)
# Créer un modèle de bruit
noise_model = NoiseModel()
# Ajouter du bruit de dépolarisation : 5% de chance d'erreur par porte
error_gate = depolarizing_error(0.05, 1) # 1 qubit
noise_model.add_all_qubit_quantum_error(error_gate, ['h', 'x', 'y', 'z'])
# Simuler SANS bruit (référence)
sim_ideal = AerSimulator()
result_ideal = sim_ideal.run(transpile(qc, sim_ideal), shots=10000).result()
counts_ideal = result_ideal.get_counts()
print(f"Idéal : {counts_ideal}")
# → {'0': ~5000, '1': ~5000} (50/50 parfait)
# Simuler AVEC bruit
sim_noisy = AerSimulator(noise_model=noise_model)
result_noisy = sim_noisy.run(transpile(qc, sim_noisy), shots=10000).result()
counts_noisy = result_noisy.get_counts()
print(f"Bruité : {counts_noisy}")
# → {'0': ~5125, '1': ~4875} (le bruit biaise légèrement les résultats)
Bruit en Q# — modèle conceptuel
// Q# — Opération illustrant l'effet du bruit sur un qubit
// Q# ne simule pas nativement le bruit (c'est un langage haut niveau),
// mais on peut modéliser l'effet conceptuellement.
operation SimulerBitFlip(qubit : Qubit, probErreur : Double) : Unit {
// Simuler un bit-flip aléatoire
// En pratique, on utilise un simulateur externe (Azure Quantum)
// pour injecter ce type d'erreur.
// Conceptuellement :
// Avec probabilité probErreur, appliquer X (bit-flip)
// Avec probabilité 1 - probErreur, ne rien faire
// En Q# pur, on peut utiliser DrawRandomDouble pour simuler :
let tirage = DrawRandomDouble(0.0, 1.0);
if tirage < probErreur {
X(qubit); // Bit-flip !
Message("⚠ Bit-flip appliqué par le bruit !");
}
}
operation DemoCircuitBruite() : Result {
use q = Qubit();
H(q); // Superposition
// Le bruit frappe entre les portes
SimulerBitFlip(q, 0.05); // 5% de chance de flip
let resultat = M(q);
Reset(q);
return resultat;
}
À retenir : Le bruit n’est pas un bug qu’on peut « patcher » dans le code. C’est une propriété physique fondamentale de toute implémentation réelle. Chaque qubit réel a un T1, un T2, et un taux d’erreur par porte. La question n’est pas « comment éviter le bruit ? » mais « comment calculer correctement malgré le bruit ? ». C’est tout l’objet du thème suivant.
Correction d’erreur — bases
Le défi : protéger l’information quantique
En informatique classique, la correction d’erreur est simple : on copie le bit. Si tu as le bit 1, tu le dupliques en 111. Si le bruit corrompt un bit, la majorité l’emporte et tu récupères la valeur correcte. Mais en quantique, le théorème de non-clonage (vu en jour 10-11) interdit de copier un état quantique inconnu.
Le problème : On ne peut pas copier. On ne peut pas mesurer (ça détruit la superposition). Pourtant, il faut détecter et corriger les erreurs. Comment faire ?
La solution est astucieuse : on encode l’information d’un qubit logique dans plusieurs qubits physiques, de sorte que les erreurs affectent les qubits physiques sans détruire l’information logique. On ne copie pas l’état — on le distribue dans un espace plus grand.
Code à 3 qubits — bit-flip
Le code à 3 qubits est le plus simple. Il protège contre les erreurs de type bit-flip (X). L’idée :
Encodage : L’état α|0⟩ + β|1⟩ est encodé en α|000⟩ + β|111⟩. On utilise deux CNOT pour « étaler » l’information sur 3 qubits.
Attention : Ce n’est PAS du clonage ! On ne crée pas trois copies de
α|0⟩ + β|1⟩. On crée un état intriqué à 3 qubits. Les α et β ne sont pas copiés individuellement — ils sont partagés collectivement.
Détection : On mesure la parité entre les paires de qubits sans mesurer les qubits individuellement. C’est la mesure de syndrome :
- Syndrome (q1⊕q2, q2⊕q3) = (0, 0) → pas d’erreur
- Syndrome (1, 0) → erreur sur le qubit 1
- Syndrome (1, 1) → erreur sur le qubit 2
- Syndrome (0, 1) → erreur sur le qubit 3
Correction : On applique un X sur le qubit identifié par le syndrome.
| Syndrome (s₁, s₂) | Interprétation | Action corrective |
|---|---|---|
| (0, 0) | Aucune erreur | Ne rien faire |
| (1, 0) | Bit-flip sur qubit 1 | Appliquer X sur qubit 1 |
| (1, 1) | Bit-flip sur qubit 2 | Appliquer X sur qubit 2 |
| (0, 1) | Bit-flip sur qubit 3 | Appliquer X sur qubit 3 |
Point clé — Mesure de syndrome : La mesure de syndrome ne mesure PAS la valeur du qubit logique. Elle mesure uniquement les corrélations entre qubits (parité). C’est comme demander « est-ce que ces deux qubits sont d’accord ? » sans demander « ils valent combien ? ». L’information logique (α et β) n’est pas perturbée.
Code à 3 qubits en Qiskit
from qiskit import QuantumCircuit
def code_3_qubits_bitflip():
"""Code de correction d'erreur à 3 qubits (bit-flip)."""
# 3 qubits de données + 2 qubits ancilla pour le syndrome
qc = QuantumCircuit(5, 2)
# --- Étape 1 : Préparer l'état logique ---
# On encode |ψ⟩ = α|0⟩ + β|1⟩ (ici, une superposition quelconque)
qc.ry(1.23, 0) # État arbitraire sur le qubit 0
qc.barrier()
# --- Étape 2 : Encoder dans 3 qubits ---
# α|0⟩ + β|1⟩ → α|000⟩ + β|111⟩
qc.cx(0, 1) # CNOT : qubit 0 contrôle qubit 1
qc.cx(0, 2) # CNOT : qubit 0 contrôle qubit 2
qc.barrier()
# --- Étape 3 : Simuler une erreur bit-flip sur le qubit 1 ---
qc.x(1) # ← Le bruit retourne le qubit 1
qc.barrier()
# --- Étape 4 : Mesure de syndrome ---
# Ancilla qubit 3 : parité de (qubit 0, qubit 1)
qc.cx(0, 3)
qc.cx(1, 3)
# Ancilla qubit 4 : parité de (qubit 1, qubit 2)
qc.cx(1, 4)
qc.cx(2, 4)
# Mesurer les ancillas
qc.measure(3, 0) # s1
qc.measure(4, 1) # s2
qc.barrier()
# --- Étape 5 : Correction conditionnelle ---
# Si syndrome = (1,0) → flip qubit 0
# Si syndrome = (1,1) → flip qubit 1
# Si syndrome = (0,1) → flip qubit 2
# (En pratique, on utilise des classically-controlled gates)
return qc
circuit = code_3_qubits_bitflip()
print(circuit.draw())
# Le syndrome sera (1,1) → erreur sur le qubit 1, comme attendu
Le code de Shor à 9 qubits
Le code à 3 qubits ne corrige que les bit-flips. Mais en réalité, un qubit peut aussi subir des phase-flips (la porte Z). Le code de Shor (1995) combine les deux protections en utilisant 9 qubits physiques pour un seul qubit logique.
La stratégie en deux couches :
-
Couche externe — phase-flip : On encode
α|0⟩ + β|1⟩enα|+++⟩ + β|---⟩(dans la base de Hadamard). Un code à 3 qubits dans la base X protège contre les phase-flips. -
Couche interne — bit-flip : Chaque
|+⟩et|-⟩est lui-même encodé avec un code à 3 qubits dans la base Z, protégeant contre les bit-flips.
Résultat : |0⟩ logique → (|000⟩ + |111⟩)(|000⟩ + |111⟩)(|000⟩ + |111⟩) / 2√2
Analogie : Imagine un coffre-fort avec deux systèmes de sécurité indépendants — une serrure mécanique (contre les bit-flips) et un code électronique (contre les phase-flips). Même si un cambrioleur sait crocheter un type de serrure, l’autre le bloque. Le code de Shor empile deux protections orthogonales.
Mesure de syndrome en Q#
// Q# — Mesure de syndrome pour un code à 3 qubits (bit-flip)
operation MesureSyndrome(qubits : Qubit[]) : (Result, Result) {
// On a besoin de 2 qubits ancilla pour mesurer la parité
use ancilla0 = Qubit();
use ancilla1 = Qubit();
// Parité entre qubit 0 et qubit 1
CNOT(qubits[0], ancilla0);
CNOT(qubits[1], ancilla0);
// Parité entre qubit 1 et qubit 2
CNOT(qubits[1], ancilla1);
CNOT(qubits[2], ancilla1);
// Mesurer les ancillas (ne touche PAS les qubits de données)
let s1 = M(ancilla0);
let s2 = M(ancilla1);
// Réinitialiser les ancillas
Reset(ancilla0);
Reset(ancilla1);
return (s1, s2);
}
operation CorrigerBitFlip(qubits : Qubit[]) : Unit {
let (s1, s2) = MesureSyndrome(qubits);
// Décoder le syndrome et corriger
if s1 == One and s2 == Zero {
X(qubits[0]); // Erreur sur qubit 0
Message("Correction : bit-flip sur qubit 0");
} elif s1 == One and s2 == One {
X(qubits[1]); // Erreur sur qubit 1
Message("Correction : bit-flip sur qubit 1");
} elif s1 == Zero and s2 == One {
X(qubits[2]); // Erreur sur qubit 2
Message("Correction : bit-flip sur qubit 2");
} else {
Message("Aucune erreur détectée");
}
}
Limites et perspective
Le code de Shor utilise 9 qubits physiques pour protéger 1 qubit logique. C’est un ratio coûteux. Les codes modernes comme le code de surface (surface code) sont bien plus efficaces et constituent la base des plans de passage à l’échelle de Google, IBM et Microsoft. Mais le principe reste le même : encoder, détecter via le syndrome, corriger sans mesurer l’état logique.
À retenir : La correction d’erreur quantique est indispensable pour tout calcul quantique utile à grande échelle. Sans elle, le bruit accumule des erreurs qui rendent le résultat inutilisable après quelques dizaines de portes. Avec elle, on peut — en théorie — calculer aussi longtemps qu’on veut, à condition d’avoir suffisamment de qubits physiques. C’est le concept de tolérance aux fautes (fault tolerance).