Skip to main content
IBM Quantum Platform

Algorithme de Deutsch

L'algorithme de Deutsch résout le problème de parité dans le cas particulier où n=1.n = 1. Dans le contexte de l'informatique quantique, ce problème est parfois appelé problème de Deutsch, et nous suivrons cette nomenclature dans cette leçon.

Pour être précis, l'entrée est représentée par une fonction f:ΣΣf:\Sigma \rightarrow \Sigma d'un bit à un bit. Ces fonctions sont au nombre de quatre :

af1(a)0010af2(a)0011af3(a)0110af4(a)0111\rule[-10mm]{0mm}{10mm} \begin{array}{c|c} a & f_1(a)\\ \hline 0 & 0\\ 1 & 0 \end{array} \qquad \begin{array}{c|c} a & f_2(a)\\ \hline 0 & 0\\ 1 & 1 \end{array} \qquad \begin{array}{c|c} a & f_3(a)\\ \hline 0 & 1\\ 1 & 0 \end{array} \qquad \begin{array}{c|c} a & f_4(a)\\ \hline 0 & 1\\ 1 & 1 \end{array}

La première et la dernière de ces fonctions sont constantes et les deux autres sont équilibrées, ce qui signifie que les deux valeurs de sortie possibles pour la fonction se produisent le même nombre de fois lorsque nous parcourons les entrées. Le problème de Deutsch est de déterminer à laquelle de ces deux catégories la fonction d'entrée appartient : constante ou équilibrée.

Deutsch's problem

Entrée : une fonction f:{0,1}{0,1}f:\{0,1\}\rightarrow\{0,1\} \ Sortie : 00 si ff est constant, 11 si ff est équilibré

Si nous considérons la fonction d'entrée ff dans le problème de Deutsch comme représentant un accès aléatoire à une chaîne de caractères, nous pensons à une chaîne de deux bits : f(0)f(1).f(0)f(1).

functionstringf100f201f310f411\begin{array}{cc} \mathsf{function} & \mathsf{string}\\ \hline f_1 & 00 \\ f_2 & 01 \\ f_3 & 10 \\ f_4 & 11 \end{array}

Vu sous cet angle, le problème de Deutsch consiste à calculer la parité (ou, de manière équivalente, le OU exclusif) des deux bits.

Tout algorithme d'interrogation classique qui résout correctement ce problème doit interroger les deux bits : f(0)f(0) et f(1).f(1). Si nous apprenons que f(1)=1,f(1) = 1, par exemple, la réponse pourrait toujours être 00 ou 1,1, selon que f(0)=1f(0) = 1 ou f(0)=0,f(0) = 0, respectivement. Tous les autres cas sont similaires : la connaissance d'un seul des deux bits ne fournit aucune information sur leur parité. Le circuit booléen décrit dans la section précédente est donc le meilleur que nous puissions faire en termes de nombre de requêtes nécessaires pour résoudre ce problème.


Description du circuit quantique

L'algorithme de Deutsch résout le problème de Deutsch à l'aide d'une seule requête, offrant ainsi un avantage quantifiable des calculs quantiques par rapport aux calculs classiques. Il s'agit peut-être d'un avantage modeste - une requête au lieu de deux - mais il faut bien commencer quelque part. Les avancées scientifiques ont parfois des origines apparemment modestes.

Voici un circuit quantique qui décrit l'algorithme de Deutsch :

Algorithme de Deutsch

Analyse

Pour analyser l'algorithme de Deutsch, nous allons retracer l'action du circuit ci-dessus et identifier les états des qubits aux moments suggérés par cette figure :

États pendant l'algorithme de Deutsch

L'état initial est 10,\vert 1\rangle \vert 0 \rangle, et les deux opérations Hadamard sur le côté gauche du circuit transforment cet état en

π1=+=12(01)0+12(01)1.\vert \pi_1 \rangle = \vert - \rangle \vert + \rangle = \frac{1}{2} \bigl( \vert 0\rangle - \vert 1\rangle \bigr) \vert 0\rangle + \frac{1}{2} \bigl( \vert 0\rangle - \vert 1\rangle \bigr) \vert 1\rangle.

(Comme toujours, nous suivons la convention d'ordonnancement des qubits de Qiskit, qui place le qubit supérieur à droite et le qubit inférieur à gauche) Il peut sembler peu intuitif d'écrire l'état de ce produit partiellement distribué (en laissant les états du qubit 1 pris en compte), mais cela rendra nos expressions ultérieures plus compactes.

Ensuite, la porte UfU_f est exécutée. Selon la définition de la porte UfU_f, la valeur de la fonction ff pour l'état classique du qubit supérieur/le plus à droite est XORée sur le qubit inférieur/le plus à gauche, ce qui transforme π1\vert \pi_1\rangle en l'état

π2=12(0f(0)1f(0))0+12(0f(1)1f(1))1.\vert \pi_2 \rangle = \frac{1}{2} \bigl( \vert 0 \oplus f(0) \rangle - \vert 1 \oplus f(0) \rangle \bigr) \vert 0 \rangle + \frac{1}{2} \bigl( \vert 0 \oplus f(1) \rangle - \vert 1 \oplus f(1) \rangle \bigr) \vert 1 \rangle.

Nous pouvons simplifier cette expression en observant que la formule

0a1a=(1)a(01)\vert 0 \oplus a\rangle - \vert 1 \oplus a\rangle = (-1)^a \bigl( \vert 0\rangle - \vert 1\rangle \bigr)

fonctionne pour les deux valeurs possibles aΣ.a\in\Sigma. Plus explicitement, les deux cas sont les suivants.

0010=01=(1)0(01)0111=10=(1)1(01)\begin{aligned} \vert 0 \oplus 0\rangle - \vert 1 \oplus 0\rangle & = \vert 0 \rangle - \vert 1 \rangle = (-1)^0 \bigl( \vert 0\rangle - \vert 1\rangle \bigr)\\ \vert 0 \oplus 1\rangle - \vert 1 \oplus 1\rangle & = \vert 1 \rangle - \vert 0\rangle = (-1)^1 \bigl( \vert 0\rangle - \vert 1\rangle \bigr) \end{aligned}

Nous pouvons donc exprimer π2\vert\pi_2\rangle de la manière suivante :

π2=12(1)f(0)(01)0+12(1)f(1)(01)1=((1)f(0)0+(1)f(1)12).\begin{aligned} \vert\pi_2\rangle & = \frac{1}{2} (-1)^{f(0)} \bigl( \vert 0 \rangle - \vert 1 \rangle \bigr) \vert 0 \rangle + \frac{1}{2} (-1)^{f(1)} \bigl( \vert 0 \rangle - \vert 1 \rangle \bigr) \vert 1 \rangle \\ & = \vert - \rangle \biggl( \frac{(-1)^{f(0)} \vert 0\rangle + (-1)^{f(1)} \vert 1\rangle}{\sqrt{2}}\biggr). \end{aligned}

Il vient de se passer quelque chose d'intéressant! Bien que l'action de la porte UfU_f sur les états de base standard laisse le qubit supérieur/le plus à droite seul et XOR la valeur de la fonction sur le qubit inférieur/le plus à gauche, nous voyons ici que l'état du qubit supérieur/le plus à droite a changé (en général) tandis que l'état du qubit inférieur/le plus à gauche reste le même - étant spécifiquement dans l'état \vert - \rangle avant et après l'exécution de la porte UfU_f. Ce phénomène est connu sous le nom de " retour de phase" et nous y reviendrons.

Avec une dernière simplification, qui consiste à retirer le facteur (1)f(0)(-1)^{f(0)} de la somme, nous obtenons cette expression de l'état π2\vert\pi_2\rangle :

π2=(1)f(0)(0+(1)f(0)f(1)12)={(1)f(0)+if f(0)f(1)=0(1)f(0)if f(0)f(1)=1.\begin{aligned} \vert\pi_2\rangle & = (-1)^{f(0)} \vert - \rangle \biggl( \frac{\vert 0\rangle + (-1)^{f(0) \oplus f(1)} \vert 1\rangle}{\sqrt{2}}\biggr) \\ & = \begin{cases} (-1)^{f(0)} \vert - \rangle \vert + \rangle & \text{if $f(0) \oplus f(1) = 0$}\\[1mm] (-1)^{f(0)} \vert - \rangle \vert - \rangle & \text{if $f(0) \oplus f(1) = 1$}. \end{cases} \end{aligned}

Remarquez que dans cette expression, nous avons f(0)f(1)f(0) \oplus f(1) dans l'exposant de 1-1 au lieu de f(1)f(0),f(1) - f(0),, ce qui est ce que nous pourrions attendre d'un point de vue purement algébrique, mais nous obtenons le même résultat d'une manière ou d'une autre. En effet, la valeur (1)k(-1)^k pour tout entier kk dépend uniquement du fait que kk est pair ou impair.

L'application de la dernière porte de Hadamard au qubit supérieur nous donne l'état suivant

π3={(1)f(0)0if f(0)f(1)=0(1)f(0)1if f(0)f(1)=1,\vert \pi_3 \rangle = \begin{cases} (-1)^{f(0)} \vert - \rangle \vert 0 \rangle & \text{if $f(0) \oplus f(1) = 0$}\\[1mm] (-1)^{f(0)} \vert - \rangle \vert 1 \rangle & \text{if $f(0) \oplus f(1) = 1$}, \end{cases}

ce qui conduit au résultat correct avec la probabilité 11 lorsque le qubit de droite/le plus haut est mesuré.


Remarques supplémentaires sur le recul de phase

Avant de poursuivre, examinons l'analyse ci-dessus sous un angle légèrement différent qui pourrait nous éclairer sur le phénomène du retour de phase.

Tout d'abord, il convient de noter que la formule suivante fonctionne pour tous les choix de bits b,cΣ.b,c\in\Sigma.

bc=Xcb\vert b \oplus c\rangle = X^c \vert b \rangle

On peut s'en assurer en le vérifiant pour les deux valeurs possibles c=0c = 0 et c=1c = 1 :

b0=b=Ib=X0bb1=¬b=Xb=X1b.\begin{aligned} \vert b \oplus 0 \rangle & = \vert b\rangle = \mathbb{I} \vert b \rangle = X^0 \vert b \rangle\\ \vert b \oplus 1 \rangle & = \vert \neg b\rangle = X \vert b \rangle = X^1 \vert b \rangle. \end{aligned}

En utilisant cette formule, nous constatons que

Uf(ba)=bf(a)a=(Xf(a)b)aU_f \bigl(\vert b\rangle \vert a \rangle\bigr) = \vert b \oplus f(a) \rangle \vert a \rangle = \bigl(X^{f(a)}\vert b \rangle\bigr) \vert a \rangle

pour chaque choix de bits a,bΣ.a,b\in\Sigma. Comme cette formule est vraie pour b=0b=0 et b=1,b=1,, nous voyons par linéarité que

Uf(ψa)=(Xf(a)ψ)aU_f \bigl( \vert \psi \rangle \vert a \rangle \bigr) = \bigl(X^{f(a)}\vert \psi \rangle\bigr) \vert a \rangle

pour tous les vecteurs d'état des qubits ψ,\vert \psi\rangle, et donc

Uf(a)=(Xf(a))a=(1)f(a)a.U_f \bigl( \vert - \rangle \vert a \rangle \bigr) = \bigl(X^{f(a)} \vert - \rangle \bigr) \vert a \rangle = (-1)^{f(a)} \vert - \rangle \vert a \rangle.

La clé de ce fonctionnement est la suivante X=.X\vert - \rangle = - \vert - \rangle. En termes mathématiques, le vecteur \vert - \rangle est un vecteur propre de la matrice XX ayant pour valeur propre 1.-1.

Nous aborderons les vecteurs propres et les valeurs propres plus en détail dans la prochaine leçon sur l' estimation de phase et la factorisation, où le phénomène de rebond de phase est généralisé à d'autres opérations unitaires.

En gardant à l'esprit que les scalaires flottent librement à travers les produits tensoriels, nous trouvons une autre façon de raisonner comment l'opération UfU_f transforme π1\vert \pi_1\rangle en π2\vert \pi_2\rangle dans l'analyse ci-dessus :

π2=Uf(+)=12Uf(0)+12Uf(1)=((1)f(0)0+(1)f(1)12).\begin{aligned} \vert \pi_2 \rangle & = U_f \bigl( \vert - \rangle \vert + \rangle \bigr)\\ & = \frac{1}{\sqrt{2}} U_f \bigl(\vert - \rangle \vert 0\rangle \bigr) + \frac{1}{\sqrt{2}} U_f \bigl(\vert - \rangle \vert 1\rangle \bigr)\\ & = \vert - \rangle \biggl( \frac{(-1)^{f(0)} \vert 0\rangle + (-1)^{f(1)} \vert 1\rangle}{\sqrt{2}}\biggr). \end{aligned}

Implémentation dans Qiskit

Voyons maintenant comment nous pouvons implémenter l'algorithme de Deutsch dans Qiskit. Nous commencerons par vérifier la version, puis nous effectuerons les importations nécessaires uniquement pour cette mise en œuvre. Pour les implémentations d'autres algorithmes qui suivent, nous effectuerons les importations nécessaires séparément dans un souci de plus grande modularité.

from qiskit import __version__

print(__version__)

Output:

2.1.1
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator

Tout d'abord, nous allons définir un circuit quantique qui met en œuvre une porte d'interrogation pour l'une des quatre fonctions f1,f_1, f2,f_2, f3,f_3, ou f4f_4 d'un bit à un bit décrites précédemment. Comme nous l'avons déjà mentionné, la mise en œuvre des portes d'interrogation ne fait pas vraiment partie de l'algorithme de Deutsch lui-même; ici, nous montrons essentiellement une façon de préparer l'entrée, sous la forme d'une implémentation de circuit d'une porte d'interrogation.

def deutsch_function(case: int):
    # This function generates a quantum circuit for one of the 4 functions
    # from one bit to one bit

    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

Nous pouvons voir à quoi ressemble chaque circuit en utilisant la méthode draw . Voici le circuit de la fonction f3.f_3.

display(deutsch_function(3).draw(output="mpl"))

Output:

Output of the previous code cell

Ensuite, nous créerons le circuit quantique réel pour l'algorithme de Deutsch, en remplaçant la porte d'interrogation par une implémentation de circuit quantique donnée en argument. Nous brancherons bientôt l'un des quatre circuits définis par la fonction deutsch_function que nous avons définie plus tôt. Des barrières sont incluses pour montrer la séparation visuelle entre l'implémentation de la porte d'interrogation et le reste du circuit.

def compile_circuit(function: QuantumCircuit):
    # Compiles a circuit for use in Deutsch's algorithm.

    n = function.num_qubits - 1
    qc = QuantumCircuit(n + 1, n)

    qc.x(n)
    qc.h(range(n + 1))

    qc.barrier()
    qc.compose(function, inplace=True)
    qc.barrier()

    qc.h(range(n))
    qc.measure(range(n), range(n))

    return qc

Une fois de plus, nous pouvons voir à quoi ressemble le circuit en utilisant la méthode draw .

display(compile_circuit(deutsch_function(3)).draw(output="mpl"))

Output:

Output of the previous code cell

Enfin, nous créerons une fonction qui exécutera une fois le circuit défini précédemment et produira le résultat approprié : "constant" ou "équilibré"

def deutsch_algorithm(function: QuantumCircuit):
    # Determine if a one-bit function is constant or balanced.

    qc = compile_circuit(function)

    result = AerSimulator().run(qc, shots=1, memory=True).result()
    measurements = result.get_memory()
    if measurements[0] == "0":
        return "constant"
    return "balanced"

Nous pouvons maintenant exécuter l'algorithme de Deutsch sur n'importe laquelle des quatre fonctions définies ci-dessus.

f = deutsch_function(3)
display(deutsch_algorithm(f))

Output:

'balanced'
Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.