L'algorithme de Deutsch-Jozsa
Pour ce module Qiskit en classe, les étudiants doivent disposer d'un environnement Python fonctionnel avec les packages suivants installés :
qiskitv2.1.0 ou plus récentqiskit-ibm-runtimev0.40.1 ou plus récentqiskit-aerv0.17.0 ou plus récentqiskit.visualizationnumpypylatexenc
Pour configurer et installer les packages ci-dessus, consulte le guide Installer Qiskit. Pour exécuter des tâches sur de vrais ordinateurs quantiques, les étudiants devront créer un compte IBM Quantum® en suivant les étapes du guide Configurer ton compte IBM Cloud.
Ce module a été testé et a utilisé quatre secondes de temps QPU. Il s'agit d'une estimation uniquement. Ton utilisation réelle peut varier.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'
Regarde la présentation du module par Dr Katie McCormick ci-dessous, ou clique ici pour la regarder sur YouTube.
Introduction
Au début des années 1980, les physiciens quantiques et les informaticiens avaient une vague notion que la mécanique quantique pouvait être exploitée pour effectuer des calculs bien plus puissants que ce que les ordinateurs classiques peuvent faire. Leur raisonnement était le suivant : il est difficile pour un ordinateur classique de simuler des systèmes quantiques, mais un ordinateur quantique devrait pouvoir le faire plus efficacement. Et si un ordinateur quantique pouvait simuler des systèmes quantiques plus efficacement, peut-être y avait-il d'autres tâches qu'il pourrait accomplir plus efficacement qu'un ordinateur classique.
La logique était solide, mais les détails restaient à élaborer. Cela a commencé en 1985, quand David Deutsch a décrit le premier « ordinateur quantique universel ». Dans ce même article, il a fourni le premier exemple de problème pour lequel un ordinateur quantique pouvait résoudre quelque chose plus efficacement qu'un ordinateur classique. Ce premier exemple jouet est désormais connu sous le nom d'« algorithme de Deutsch ». L'amélioration apportée par l'algorithme de Deutsch était modeste, mais Deutsch a travaillé avec Richard Jozsa quelques années plus tard pour élargir davantage l'écart entre les ordinateurs classiques et quantiques.
Ces algorithmes — celui de Deutsch, et l'extension Deutsch-Jozsa — ne sont pas particulièrement utiles, mais ils restent vraiment importants pour plusieurs raisons :
- Historiquement, ils ont été parmi les premiers algorithmes quantiques dont on a démontré qu'ils surpassaient leurs équivalents classiques. Les comprendre peut nous aider à saisir comment la réflexion de la communauté sur l'informatique quantique a évolué au fil du temps.
- Ils peuvent nous aider à comprendre certains aspects de la réponse à une question étonnamment subtile : d'où vient la puissance de l'informatique quantique ? Parfois, les ordinateurs quantiques sont comparés à d'énormes processeurs parallèles à échelle exponentielle. Mais ce n'est pas tout à fait exact. Si une partie de la réponse réside dans ce qu'on appelle le « parallélisme quantique », extraire le maximum d'informations en une seule exécution est un art subtil. Les algorithmes de Deutsch et Deutsch-Jozsa montrent comment y parvenir.
Dans ce module, nous allons découvrir l'algorithme de Deutsch, l'algorithme de Deutsch-Jozsa, et ce qu'ils nous enseignent sur la puissance de l'informatique quantique.
Le parallélisme quantique et ses limites
Une partie de la puissance de l'informatique quantique provient du « parallélisme quantique », c'est-à-dire essentiellement la capacité d'effectuer des opérations sur plusieurs entrées en même temps, car les états d'entrée des qubits peuvent être en superposition de plusieurs états classiquement autorisés. CEPENDANT, bien qu'un circuit quantique puisse être capable d'évaluer plusieurs états d'entrée à la fois, il est impossible d'extraire toutes ces informations en une seule opération.
Pour comprendre ce que je veux dire, supposons que nous ayons un bit, , et une fonction appliquée à ce bit, . Il existe quatre fonctions binaires possibles qui prennent un seul bit et retournent un seul bit :
| 0 | 0 | 0 | 1 | 1 |
| 1 | 0 | 1 | 0 | 1 |
Nous aimerions savoir laquelle de ces fonctions (1 à 4) est notre . Classiquement, nous devrions exécuter la fonction deux fois — une fois pour , une fois pour . Mais voyons si nous pouvons faire mieux avec un circuit quantique. Nous pouvons en apprendre davantage sur la fonction grâce à la porte suivante :
Ici, la porte calcule , où est l'état du qubit 0, et l'applique au qubit 1. Ainsi, l'état résultant, , devient simplement quand . Cela contient toutes les informations dont nous avons besoin pour connaître la fonction : le qubit 0 nous dit ce qu'est , et le qubit 1 nous dit ce qu'est . Donc, si nous initialisons , alors l'état final des deux qubits sera : . Mais comment accéder à ces informations ?
2.1. Essaie avec Qiskit :
Avec Qiskit, nous allons sélectionner aléatoirement l'une des quatre fonctions possibles ci-dessus et exécuter le circuit. Ta tâche est ensuite d'utiliser les mesures du circuit quantique pour découvrir la fonction en un minimum d'exécutions.
Dans cette première expérience et tout au long du module, nous utiliserons un cadre de travail pour l'informatique quantique appelé « Qiskit patterns », qui décompose les flux de travail en les étapes suivantes :
- Étape 1 : Mapper les entrées classiques vers un problème quantique
- Étape 2 : Optimiser le problème pour l'exécution quantique
- Étape 3 : Exécuter en utilisant les Primitives Qiskit Runtime
- Étape 4 : Post-traitement et analyse classique
Commençons par charger quelques packages nécessaires, y compris les primitives Qiskit Runtime. Nous sélectionnerons également l'ordinateur quantique le moins chargé disponible.
Il y a du code ci-dessous pour enregistrer tes identifiants lors de la première utilisation. Assure-toi de supprimer ces informations du notebook après les avoir sauvegardées dans ton environnement, afin que tes identifiants ne soient pas partagés accidentellement quand tu partages le notebook. Consulte Configurer ton compte IBM Cloud et Initialiser le service dans un environnement non fiable pour plus de conseils.
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
# Load the Runtime primitive and session
from qiskit_ibm_runtime import SamplerV2 as Sampler
# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform', instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR_API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')
# Load saved credentials
service = QiskitRuntimeService()
# Use the least busy backend, or uncomment the loading of a specific backend like "ibm_brisbane".
# backend = service.least_busy(operational=True, simulator=False, min_num_qubits = 127)
backend = service.backend("ibm_brisbane")
print(backend.name)
sampler = Sampler(mode=backend)
ibm_brisbane
La cellule ci-dessous te permettra de basculer entre l'utilisation du simulateur ou du vrai matériel tout au long du notebook. Nous te recommandons de l'exécuter maintenant :
# Load the backend sampler
from qiskit.primitives import BackendSamplerV2
# Load the Aer simulator and generate a noise model based on the currently-selected backend.
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel
# Alternatively, load a fake backend with generic properties and define a simulator.
noise_model = NoiseModel.from_backend(backend)
# Define a simulator using Aer, and use it in Sampler.
backend_sim = AerSimulator(noise_model=noise_model)
sampler_sim = BackendSamplerV2(backend=backend_sim)
# You could also define a simulator-based sampler using a generic backend:
# backend_gen = GenericBackendV2(num_qubits=18)
# sampler_gen = BackendSamplerV2(backend=backend_gen)
Maintenant que nous avons chargé les packages nécessaires, nous pouvons procéder au flux de travail Qiskit patterns. Dans l'étape de mapping ci-dessous, nous créons d'abord une fonction qui sélectionne parmi les quatre fonctions possibles prenant un seul bit et retournant un seul bit.
# Step 1: Map
from qiskit import QuantumCircuit
qc = QuantumCircuit(2)
def twobit_function(case: int):
"""
Generate a valid two-bit function as a `QuantumCircuit`.
"""
if case not in [1, 2, 3, 4]:
raise ValueError("`case` must be 1, 2, 3, or 4.")
f = QuantumCircuit(2)
if case in [2, 3]:
f.cx(0, 1)
if case in [3, 4]:
f.x(1)
return f
# first, convert oracle circuit (above) to a single gate for drawing purposes. otherwise, the circuit is too large to display
# blackbox = twobit_function(2).to_gate() # you may edit the number inside "twobit_function()" to select among the four valid functions
# blackbox.label = "$U_f$"
qc.h(0)
qc.barrier()
qc.compose(twobit_function(2), inplace=True)
qc.measure_all()
qc.draw("mpl")
Dans le circuit ci-dessus, la porte de Hadamard « H » prend le qubit 0, qui est initialement dans l'état , et le transforme en l'état de superposition . Ensuite, évalue la fonction et l'applique au qubit 1.
Nous devons ensuite optimiser et transpiler le circuit pour l'exécuter sur l'ordinateur quantique :
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
Enfin, nous exécutons notre circuit transpilé sur l'ordinateur quantique et visualisons nos résultats :
# Step 3: Run the job on a real quantum computer
job = sampler.run([qc_isa], shots=1)
# job = sampler_sim.run([qc_isa],shots=1) # uncomment this line to run on simulator instead
res = job.result()
counts = res[0].data.meas.get_counts()
# Step 4: Visualize and analyze results
## Analysis
from qiskit.visualization import plot_histogram
plot_histogram(counts)
Ce qui précède est un histogramme de nos résultats. Selon le nombre de shots que tu as choisi pour exécuter le circuit à l'étape 3 ci-dessus, tu pourrais voir une ou deux barres, représentant les états mesurés des deux qubits dans chaque shot. Comme toujours avec Qiskit et dans ce notebook, nous utilisons la notation « little endian », ce qui signifie que les états des qubits 0 à n sont écrits dans l'ordre croissant de droite à gauche, donc le qubit 0 est toujours le plus à droite.
Ainsi, parce que le qubit 0 était dans un état de superposition, le circuit a évalué la fonction pour les deux et en même temps — quelque chose que les ordinateurs classiques ne peuvent pas faire ! Mais l'inconvénient apparaît quand nous voulons en apprendre davantage sur la fonction — quand nous mesurons les qubits, nous effondrons leur état. Si tu sélectionnes « shots = 1 » pour n'exécuter le circuit qu'une seule fois, tu ne verras qu'une seule barre dans l'histogramme ci-dessus, et tes informations sur la fonction seront incomplètes.
Vérifie ta compréhension
Lis la ou les question(s) ci-dessous, réfléchis à ta réponse, puis clique sur le triangle pour révéler la solution.
Combien de fois devons-nous exécuter l'algorithme ci-dessus pour apprendre la fonction ? Est-ce que c'est mieux que le cas classique ? Préfères-tu un ordinateur classique ou quantique pour résoudre ce problème ?
Réponse :
Puisque la mesure va effondrer la superposition et ne retourner qu'une seule valeur, nous devons exécuter le circuit au moins deux fois pour retourner les deux sorties de la fonction et . Dans le meilleur des cas, cela fonctionne aussi bien que le cas classique, où nous calculons à la fois et lors des deux premières requêtes. Mais il y a une chance que nous ayons besoin de l'exécuter plus de deux fois, car la mesure finale est probabiliste et pourrait retourner la même valeur les deux premières fois. Je préférerais avoir un ordinateur classique dans ce cas.
Ainsi, bien que le parallélisme quantique puisse être puissant lorsqu'il est utilisé de la bonne manière, il est inexact de dire qu'un ordinateur quantique fonctionne comme un énorme processeur parallèle classique. L'acte de mesure effondre les états quantiques, donc nous ne pouvons accéder qu'à une seule sortie du calcul à la fois.
L'algorithme de Deutsch
Bien que le parallélisme quantique seul ne nous donne pas d'avantage sur les ordinateurs classiques, nous pouvons le combiner avec un autre phénomène quantique, l'interférence, pour obtenir une accélération. L'algorithme aujourd'hui connu sous le nom d'« algorithme de Deutsch » est le premier exemple d'un algorithme qui y parvient.
Le problème
Voici le problème :
Étant donné un bit d'entrée, , et une fonction d'entrée , déterminer si la fonction est équilibrée ou constante. C'est-à-dire que si elle est équilibrée, la sortie de la fonction est 0 la moitié du temps et 1 l'autre moitié. Si elle est constante, la sortie de la fonction est soit toujours 0, soit toujours 1. Rappelle-toi le tableau des quatre fonctions possibles prenant un seul bit et retournant un seul bit :
| 0 | 0 | 0 | 1 | 1 |
| 1 | 0 | 1 | 0 | 1 |
Les première et dernière fonctions, et , sont constantes, tandis que les deux fonctions du milieu, et , sont équilibrées.
L'algorithme
La façon dont Deutsch a abordé ce problème s'est faite à travers le « modèle de requête ». Dans le modèle de requête, la fonction d'entrée ( ci-dessus) est contenue dans une « boîte noire » — nous n'avons pas accès direct à son contenu, mais nous pouvons interroger la boîte noire et elle nous donnera la sortie de la fonction. On dit parfois qu'un « oracle » fournit cette information. Consulte Leçon 1 : Algorithmes de requête quantique du cours Fondamentaux des algorithmes quantiques pour en savoir plus sur le modèle de requête.
Pour déterminer si un algorithme quantique est plus efficace qu'un algorithme classique dans le modèle de requête, nous pouvons simplement comparer le nombre de requêtes que nous devons effectuer auprès de la boîte noire dans chaque cas. Dans le cas classique, pour savoir si la fonction contenue dans la boîte noire est équilibrée ou constante, nous aurions besoin d'interroger la boîte deux fois pour obtenir à la fois et .
Dans l'algorithme quantique de Deutsch, cependant, il a trouvé un moyen d'obtenir l'information avec une seule requête ! Il a apporté un ajustement au circuit de « parallélisme quantique » ci-dessus, de sorte qu'il préparait un état de superposition sur les deux qubits, au lieu de seulement sur le qubit 0. Ensuite, les deux sorties de la fonction, et , ont interféré pour retourner 0 si elles étaient toutes les deux 0 ou toutes les deux 1 (la fonction était constante), et retourner 1 si elles étaient différentes (la fonction était équilibrée). De cette façon, Deutsch pouvait différencier une fonction constante d'une fonction équilibrée avec une seule requête.
Voici un schéma du circuit de l'algorithme de Deutsch :

Pour comprendre comment cet algorithme fonctionne, examinons les états quantiques des qubits aux trois points indiqués sur le schéma ci-dessus. Essaie de trouver les états par toi-même avant de cliquer pour voir les réponses :
Vérifie ta compréhension
Lis les questions ci-dessous, réfléchis à tes réponses, puis clique sur les triangles pour révéler les solutions.
Quel est l'état ?
Réponse :
Appliquer une transformation de Hadamard transforme l'état en et l'état en . Donc, l'état complet devient :
Quel est l'état ?
Réponse :
Avant d'appliquer , rappelle-toi ce qu'il fait. Il va changer l'état du qubit 1 en fonction de l'état du qubit 0. Il est donc logique de factoriser l'état du qubit 0 : . Ensuite, si , les deux termes vont se transformer de la même façon et le signe relatif entre les deux termes reste positif, mais si , alors cela signifie que le deuxième terme va acquérir un signe moins par rapport au premier terme, changeant l'état du qubit 0 de