⚛️ 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

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 Hadamard avec 1 qubit
Un circuit quantique avec une porte Hadamard.

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()

                    
                
Circuit Hadamart avec 2 qubits
Un circuit quantique simple avec une porte Hadamard (H) et une mesure.

La porte CNOT

1. Intuition

La porte CNOT (Controlled-NOT) est une porte à deux qubits :

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}

                    
                
intrication
figure 3 : Circuit quantique avec une porte Hadamard sur le premier qubit, suivie d'une porte CNOT entre le qubit 0 (contrôle) et le qubit 1 (cible).

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')
                    
                
Circuit de l'algorithme de Deutsch avec Oracle
Circuit de l'algorithme de Deutsch-Jozsa : le premier qubit est préparé en superposition, l'oracle agit comme une boîte noire, et la mesure finale permet de déterminer si la fonction est constante ou équilibrée.

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)
                    
                
Circuit quantique de l'algorithme de Deutsch avec un oracle constant
Algorithme de Deutsch-Jozsa avec un oracle constant. Le résultat de la mesure est toujours 0, indiquant qua la fonction est constante.

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)
                    
                
Circuit quantique de l'algorithme de Deutsch avec un oracle équilibré
Algorithme de Deutsch-Jozsa avec un oracle équilibré. Le résultat de la mesure est toujours 1, indiquant qua la fonction est équilibrée.

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.