Débutant Chapitre 8-9 / 16

Portes contrôlées et CNOT & Lecture de circuits quantiques

Portes contrôlées (CNOT, CZ, Toffoli) et lecture de circuits quantiques — sans prérequis mathématiques, avec du code Q# et Qiskit.

Portes contrôlées et CNOT

L’idée clé : un qubit qui commande un autre

Une porte contrôlée, c’est comme un if en programmation : « si le qubit de contrôle est dans l’état |1⟩, alors applique telle opération sur le qubit cible ; sinon, ne fais rien. »

  • Le qubit de contrôle n’est pas modifié par l’opération — il conditionne ce qui arrive au qubit cible.
  • En superposition, le contrôle peut être |0⟩ et |1⟩ « en même temps » — la porte agit de façon conditionnelle sur chaque branche. C’est ce qui crée l’intrication.

La porte CNOT (Controlled-NOT)

La CNOT fait un bit-flip (X) sur la cible si et seulement si le contrôle vaut |1⟩. Autrement dit, un XOR : cible = cible ⊕ contrôle.

  • |00⟩ → |00⟩ — contrôle = 0, rien ne change
  • |01⟩ → |01⟩ — contrôle = 0, rien ne change
  • |10⟩ → |11⟩ — contrôle = 1, la cible flip de 0 à 1
  • |11⟩ → |10⟩ — contrôle = 1, la cible flip de 1 à 0

La porte CZ (Controlled-Z)

La CZ applique un Z (changement de phase) à la cible si le contrôle est |1⟩. Elle multiplie par −1 uniquement l’amplitude de |11⟩.

Point important : La CZ est symétrique — peu importe lequel des deux qubits est le contrôle ou la cible, le résultat est identique. Ce n’est pas le cas de la CNOT !

La porte Toffoli (CCX)

La Toffoli a deux qubits de contrôle et un qubit cible. Elle fait un X sur la cible uniquement si les deux contrôles sont |1⟩. Pensez à un if (a && b) en C#.

La Toffoli est universelle pour le calcul classique : tout circuit booléen peut être construit avec des Toffoli. C’est le pont entre le monde classique et quantique.

Tableau récapitulatif

PorteContrôle(s)Action sur cibleQ#Qiskit
CNOT1 qubitX (bit-flip)CNOT(ctrl, tgt)qc.cx(ctrl, tgt)
CZ1 qubitZ (phase-flip)CZ(ctrl, tgt)qc.cz(ctrl, tgt)
Toffoli2 qubitsX (bit-flip)CCNOT(c1, c2, tgt)qc.ccx(c1, c2, tgt)

Exemple Q# — créer un état de Bell avec CNOT

// Q# : créer l'état de Bell |Φ+⟩ = (|00⟩ + |11⟩) / √2
operation CreateBellPair() : (Result, Result) {
    use (ctrl, tgt) = (Qubit(), Qubit());
    H(ctrl);          // met ctrl en superposition |+⟩
    CNOT(ctrl, tgt);  // intrication : si ctrl=|1⟩, flip tgt
    // État résultant : (|00⟩ + |11⟩) / √2
    let r1 = M(ctrl);
    let r2 = M(tgt);
    Reset(ctrl);
    Reset(tgt);
    return (r1, r2);  // toujours corrélés : 00 ou 11
}

Exemple Qiskit — Toffoli et mesure

# Qiskit : Toffoli — flip cible seulement si les 2 contrôles = |1⟩
from qiskit import QuantumCircuit
qc = QuantumCircuit(3, 1)
qc.x(0)          # met q0 = |1⟩
qc.x(1)          # met q1 = |1⟩
qc.ccx(0, 1, 2)  # Toffoli : q2 flip car q0=q1=|1⟩
qc.measure(2, 0)
# Résultat : q2 = |1⟩ avec 100% de probabilité

⚠️ Piège courant : L’ordre des arguments compte ! En Qiskit, qc.cx(0, 1) signifie « q0 contrôle, q1 cible ». Si vous inversez, le circuit fait tout autre chose.


Lecture de circuits quantiques

Un circuit quantique, c’est du code visuel

  • Un circuit se lit de gauche à droite — comme du code qui s’exécute séquentiellement. Chaque colonne verticale représente un instant.
  • Chaque ligne horizontale (fil) représente un qubit. Le fil du haut est souvent q0.
  • La mesure est toujours en fin de circuit. Après la mesure, le qubit est « classique ».

Conventions graphiques essentielles

SymboleSignification
Boîte avec lettre (H, X, Z…)Porte mono-qubit sur ce fil
● relié à ⊕CNOT : ● = contrôle, ⊕ = cible
● relié à ●CZ : symétrique
●●⊕Toffoli : 2 contrôles + 1 cible
Compteur / double traitMesure dans la base computationnelle
Trait en pointillé (barrier)Séparateur visuel (aucun effet physique)

Lire un circuit étape par étape

Prenons le circuit de Bell :

  1. Étape 1 : Tous les qubits démarrent à |0⟩.
  2. Étape 2 : H sur q0 → superposition (|0⟩+|1⟩)/√2.
  3. Étape 3 : CNOT(q0, q1) → intrication (|00⟩+|11⟩)/√2.
  4. Étape 4 : Mesure → 00 ou 11, chacun à 50%.

Équivalence circuit ↔ code

Chaque porte du circuit correspond à une ligne de code. L’ordre de lecture (gauche → droite) = l’ordre d’exécution.

# Qiskit : le circuit de Bell lu « visuellement »
from qiskit import QuantumCircuit
qc = QuantumCircuit(2, 2)   # 2 qubits, 2 bits classiques
qc.h(0)                     # colonne 1 : H sur q0
qc.cx(0, 1)                 # colonne 2 : CNOT ctrl=q0, tgt=q1
qc.measure([0, 1], [0, 1])  # colonne 3 : mesure
print(qc.draw())
// Q# : même circuit
operation BellCircuit() : (Result, Result) {
    use (q0, q1) = (Qubit(), Qubit());
    H(q0);           // étape 1 du circuit
    CNOT(q0, q1);    // étape 2
    let r0 = M(q0);  // étape 3
    let r1 = M(q1);
    Reset(q0); Reset(q1);
    return (r0, r1);
}

Déboguer par simulation

  • En Qiskit, Aer.get_backend('statevector_simulator') permet de voir le vecteur d’état exact après chaque porte — l’équivalent d’un breakpoint avec « watch ».
  • En Q#, DumpMachine() affiche l’état complet du registre quantique. Pensez-y comme un Console.WriteLine() pour qubits.

⚠️ Piège courant : L’ordre des qubits dans Qiskit est little-endian (q0 = bit de poids faible, en bas du circuit dessiné). Vérifiez toujours avec qc.draw() et comparez avec les résultats de mesure.


Quiz — teste tes connaissances
Débutant 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.