Avancé Chapitre 28-29 / 16

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 :

CanalCe qui se passeAnalogieOpérateurs de Kraus
Bit-flip|0⟩ ↔ |1⟩ avec probabilité pUn interrupteur qui se déclenche tout seul — la lumière passe de ON à OFF au hasard.E₀ = √(1-p) · I, E₁ = √p · X
Phase-flipLa phase s’inverse (|1⟩ acquiert un signe −) avec probabilité pL’horloge saute soudainement de 12h à 6h — l’aiguille pointe dans la direction opposée.E₀ = √(1-p) · I, E₁ = √p · Z
DépolarisationLe qubit est remplacé par un état complètement aléatoire avec probabilité pUn 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étationAction corrective
(0, 0)Aucune erreurNe rien faire
(1, 0)Bit-flip sur qubit 1Appliquer X sur qubit 1
(1, 1)Bit-flip sur qubit 2Appliquer X sur qubit 2
(0, 1)Bit-flip sur qubit 3Appliquer 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 :

  1. 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.

  2. 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).


Quiz — teste tes connaissances
Avancé 7 questions Objectif : 5/7 minimum
0/7
bonnes reponses
Objectif non atteint (minimum 5/7 requis).
Remonte relire la fiche memo ci-dessus en pretant attention aux points rates, puis clique sur « Recommencer » pour retenter.