Skip to main content
IBM Quantum Platform

L'algoritmo Deutsch-Jozsa

L'algoritmo di Deutsch supera tutti gli algoritmi classici per un problema di interrogazione, ma il vantaggio è piuttosto modesto: un'interrogazione contro due. L'algoritmo di Deutsch-Jozsa estende questo vantaggio e, di fatto, può essere utilizzato per risolvere un paio di problemi di interrogazione diversi.

Ecco una descrizione del circuito quantistico dell'algoritmo di Deutsch-Jozsa. A seconda del problema specifico da risolvere, può essere necessaria un'ulteriore fase di post-elaborazione classica, non mostrata nella figura.

Algoritmo Deutsch-Jozsa

Naturalmente, non abbiamo ancora discusso quali problemi risolve questo algoritmo; lo faremo nelle due sezioni successive.


Il problema Deutsch-Jozsa

Inizieremo con il problema di interrogazione che l'algoritmo Deutsch-Jozsa era originariamente destinato a risolvere, noto come problema Deutsch-Jozsa.

La funzione di input per questo problema ha la forma f:ΣnΣf:\Sigma^n \rightarrow \Sigma per un numero intero positivo arbitrario n.n. Come nel problema di Deutsch, il compito consiste nell'emettere 00 se ff è costante e 11 se ff è bilanciato, il che significa ancora una volta che il numero di stringhe di input su cui la funzione assume il valore 00 è uguale al numero di stringhe di input su cui la funzione assume il valore 11.

Si noti che, quando nn è più grande di 1,1,, esistono funzioni della forma f:ΣnΣf:\Sigma^n \rightarrow \Sigma che non sono né costanti né bilanciate. Ad esempio, la funzione f:Σ2Σf:\Sigma^2\rightarrow\Sigma definita come

f(00)=0f(01)=0f(10)=0f(11)=1\begin{aligned} f(00) & = 0 \\ f(01) & = 0 \\ f(10) & = 0 \\ f(11) & = 1 \end{aligned}

non rientra in nessuna delle due categorie. Per il problema di Deutsch-Jozsa, semplicemente non ci preoccupiamo di funzioni come questa: sono considerate ingressi "non importanti". Cioè, per questo problema abbiamo la promessa che ff sia costante o equilibrato.

Deutsch-Jozsa problem

Ingresso: una funzione f:{0,1}n{0,1}f:\{0,1\}^n\rightarrow\{0,1\} \ Promessa: ff è costante o bilanciato \ Output: 00 se ff è costante, 11 se ff è bilanciata

L'algoritmo di Deutsch-Jozsa, con la sua singola query, risolve questo problema nel senso seguente: se tutti i risultati delle misurazioni nn sono 0,0,, allora la funzione ff è costante; altrimenti, se almeno uno dei risultati delle misurazioni è 1,1,, allora la funzione ff è bilanciata. In altre parole, il circuito sopra descritto è seguito da una fase di post-elaborazione classica in cui viene calcolata la somma logica (OR) dei risultati delle misurazioni per ottenere il bit di uscita del problema di Deutsch-Jozsa.

Analisi dell'algoritmo

Per analizzare le prestazioni dell'algoritmo di Deutsch-Jozsa per il problema di Deutsch-Jozsa, è utile iniziare pensando all'azione di un singolo strato di porte di Hadamard. Un'operazione di Hadamard può essere espressa come una matrice nel modo consueto,

H=(12121212),H = \begin{pmatrix} \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\[2mm] \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} \end{pmatrix},

ma possiamo anche esprimere questa operazione in termini di azione sugli stati base standard:

H0=120+121H1=120121.\begin{aligned} H \vert 0\rangle & = \frac{1}{\sqrt{2}} \vert 0 \rangle + \frac{1}{\sqrt{2}} \vert 1 \rangle\\[3mm] H \vert 1\rangle & = \frac{1}{\sqrt{2}} \vert 0 \rangle - \frac{1}{\sqrt{2}} \vert 1 \rangle. \end{aligned}

Queste due equazioni possono essere combinate in un'unica formula,

Ha=120+12(1)a1=12b{0,1}(1)abb,H \vert a \rangle = \frac{1}{\sqrt{2}} \vert 0 \rangle + \frac{1}{\sqrt{2}} (-1)^a \vert 1 \rangle = \frac{1}{\sqrt{2}} \sum_{b\in\{0,1\}} (-1)^{ab} \vert b\rangle,

che è vero per entrambe le scelte di aΣ.a\in\Sigma.

Supponiamo ora che invece di un solo qubit abbiamo nn qubit e che su ognuno di essi venga eseguita un'operazione di Hadamard. L'operazione combinata sui qubit nn è descritta dal prodotto tensoriale HHH\otimes \cdots \otimes H ( nn volte), che per concisione e chiarezza scriviamo come HnH^{\otimes n}. Utilizzando la formula precedente, seguita da un'espansione e da una semplificazione, possiamo esprimere l'azione di questa operazione combinata sugli stati base standard dei qubit di nn in questo modo:

Hnxn1x1x0=(Hxn1)(Hx0)=(12yn1Σ(1)xn1yn1yn1)(12y0Σ(1)x0y0y0)=12nyn1y0Σn(1)xn1yn1++x0y0yn1y0.\begin{aligned} & H^{\otimes n} \vert x_{n-1} \cdots x_1 x_0 \rangle \\ & \qquad = \bigl(H \vert x_{n-1} \rangle \bigr) \otimes \cdots \otimes \bigl(H \vert x_{0} \rangle \bigr) \\ & \qquad = \Biggl( \frac{1}{\sqrt{2}} \sum_{y_{n-1}\in\Sigma} (-1)^{x_{n-1} y_{n-1}} \vert y_{n-1} \rangle \Biggr) \otimes \cdots \otimes \Biggl( \frac{1}{\sqrt{2}} \sum_{y_{0}\in\Sigma} (-1)^{x_{0} y_{0}} \vert y_{0} \rangle \Biggr) \\ & \qquad = \frac{1}{\sqrt{2^n}} \sum_{y_{n-1}\cdots y_0 \in \Sigma^n} (-1)^{x_{n-1}y_{n-1} + \cdots + x_0 y_0} \vert y_{n-1} \cdots y_0 \rangle. \end{aligned}

Qui, tra l'altro, stiamo scrivendo stringhe binarie di lunghezza nn come xn1x0x_{n-1}\cdots x_0 e yn1y0,y_{n-1}\cdots y_0, seguendo la convenzione di indicizzazione di Qiskit.

Questa formula ci fornisce un utile strumento per analizzare il circuito quantistico di cui sopra. Dopo l'esecuzione del primo strato di porte di Hadamard, lo stato dei qubit di n+1n+1 (compreso il qubit più a sinistra/inferiore, che viene trattato separatamente dal resto) è

(H1)(Hn00)=12nxn1x0Σnxn1x0.\bigl( H \vert 1 \rangle \bigr) \bigl( H^{\otimes n} \vert 0 \cdots 0 \rangle \bigr) = \vert - \rangle \otimes \frac{1}{\sqrt{2^n}} \sum_{x_{n-1}\cdots x_0 \in \Sigma^n} \vert x_{n-1} \cdots x_0 \rangle.

Quando viene eseguita l'operazione UfU_f, questo stato viene trasformato in

12nxn1x0Σn(1)f(xn1x0)xn1x0\vert - \rangle \otimes \frac{1}{\sqrt{2^n}} \sum_{x_{n-1}\cdots x_0 \in \Sigma^n} (-1)^{f(x_{n-1}\cdots x_0)} \vert x_{n-1} \cdots x_0 \rangle

attraverso lo stesso fenomeno di contraccolpo di fase che abbiamo visto nell'analisi dell'algoritmo di Deutsch.

Quindi viene eseguito il secondo strato di porte di Hadamard, che (in base alla formula precedente) trasforma questo stato in

12nxn1x0Σnyn1y0Σn(1)f(xn1x0)+xn1yn1++x0y0yn1y0.\vert - \rangle \otimes \frac{1}{2^n} \sum_{x_{n-1}\cdots x_0 \in \Sigma^n} \sum_{y_{n-1}\cdots y_0 \in \Sigma^n} (-1)^{f(x_{n-1}\cdots x_0) + x_{n-1}y_{n-1} + \cdots + x_0 y_0} \vert y_{n-1} \cdots y_0 \rangle.

Questa espressione sembra un po' complicata e non si può concludere molto sulle probabilità di ottenere risultati di misura diversi senza conoscere meglio la funzione f.f.

Fortunatamente, tutto ciò che dobbiamo sapere è la probabilità che ognuno dei risultati della misurazione sia 00 - perché questa è la probabilità che l'algoritmo determini che ff è costante. Questa probabilità ha una formula semplice.

12nxn1x0Σn(1)f(xn1x0)2={1if f is constant0if f is balanced\Biggl\vert \frac{1}{2^n} \sum_{x_{n-1}\cdots x_0 \in \Sigma^n} (-1)^{f(x_{n-1}\cdots x_0)} \Biggr\vert^2 = \begin{cases} 1 & \text{if $f$ is constant}\\[1mm] 0 & \text{if $f$ is balanced} \end{cases}

Si noti che questi valori corrispondono alla probabilità di misurare lo stato 0n\vert 0^{\otimes n} \rangle, piuttosto che direttamente al bit di output classico finale del problema di Deutsch-Jozsa. L'algoritmo restituisce " 00 " quando tutti i risultati delle misurazioni sono " 00 " (a indicare che " ff " è costante) e restituisce " 11 " in caso contrario (a indicare che " ff " è bilanciato).

Più in dettaglio, se ff è costante, allora o f(xn1x0)=0f(x_{n-1}\cdots x_0) = 0 per ogni stringa xn1x0,x_{n-1}\cdots x_0, nel qual caso il valore della somma è 2n,2^n, oppure f(xn1x0)=1f(x_{n-1}\cdots x_0) = 1 per ogni stringa xn1x0,x_{n-1}\cdots x_0, nel qual caso il valore della somma è 2n.-2^n. Dividendo per 2n2^n e prendendo il quadrato del valore assoluto si ottiene 1.1.

Se invece ff è bilanciato, allora ff assume il valore 00 su metà delle stringhe xn1x0x_{n-1}\cdots x_0 e il valore 11 sull'altra metà, quindi i termini +1+1 e 1-1 della somma si annullano e rimane il valore 0.0.

Concludiamo che l'algoritmo funziona correttamente a condizione che la promessa sia mantenuta.

Difficoltà classica

L'algoritmo di Deutsch-Jozsa funziona sempre, ci dà sempre la risposta corretta quando la promessa è soddisfatta e richiede una sola interrogazione. Come si confronta con gli algoritmi di interrogazione classici per il problema di Deutsch-Jozsa?

In primo luogo, qualsiasi algoritmo deterministico classico che risolva correttamente il problema di Deutsch-Jozsa deve effettuare un numero esponenziale di interrogazioni: 2n1+12^{n-1} + 1 nel caso peggiore, sono necessarie molte interrogazioni. Il ragionamento è che, se un algoritmo deterministico interroga ff su 2n12^{n-1} o meno stringhe diverse, e ottiene ogni volta lo stesso valore di funzione, allora entrambe le risposte sono ancora possibili. La funzione potrebbe essere costante o bilanciata, ma per sfortuna le query restituiscono tutte lo stesso valore della funzione.

La seconda possibilità potrebbe sembrare improbabile, ma per gli algoritmi deterministici non c'è casualità o incertezza, quindi falliranno sistematicamente su alcune funzioni. A questo proposito, abbiamo quindi un vantaggio significativo degli algoritmi quantistici rispetto a quelli classici.

C'è però una fregatura: gli algoritmi classici probabilistici possono risolvere il problema di Deutsch-Jozsa con una probabilità molto alta, utilizzando solo poche query. In particolare, se scegliamo a caso alcune stringhe diverse di lunghezza nn e interroghiamo ff su queste stringhe, è improbabile che otterremo lo stesso valore di funzione per tutte quando ff è bilanciato.

Per essere precisi, se scegliamo kk stringhe di input x1,,xkΣnx^1,\ldots,x^k \in \Sigma^n in modo uniformemente casuale, valutiamo f(x1),,f(xk),f(x^1),\ldots,f(x^k), e rispondiamo 00 se i valori della funzione sono tutti uguali, e 11 in caso contrario, allora saremo sempre corretti quando ff è costante, e sbagliati nel caso in cui ff sia bilanciato con probabilità appena superiore a % 2k+1.2^{-k + 1}. Se prendiamo ad esempio k=11,k = 11,, questo algoritmo risponderà correttamente con una probabilità maggiore di 99.999.9 %.

Per questo motivo, abbiamo ancora un vantaggio piuttosto modesto degli algoritmi quantistici rispetto a quelli classici, ma si tratta comunque di un vantaggio quantificabile che rappresenta un miglioramento rispetto all'algoritmo di Deutsch.


Deutsch-Jozsa con Qiskit

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
import numpy as np

Per implementare l'algoritmo di Deutsch-Jozsa in Qiskit, inizieremo definendo una funzione dj_query che genera un circuito quantistico che implementa un query gate, per una funzione scelta a caso che soddisfa la promessa per il problema di Deutsch-Jozsa. Con una probabilità del 50%, la funzione è costante, mentre con una variazione del 50% la funzione è bilanciata. Per ognuna di queste due possibilità, la funzione viene selezionata in modo uniforme tra le funzioni di quel tipo. L'argomento è il numero di bit di ingresso della funzione.

def dj_query(num_qubits):
    # Create a circuit implementing for a query gate for a random function
    # satisfying the promise for the Deutsch-Jozsa problem.

    qc = QuantumCircuit(num_qubits + 1)

    if np.random.randint(0, 2):
        # Flip output qubit with 50% chance
        qc.x(num_qubits)
    if np.random.randint(0, 2):
        # return constant circuit with 50% chance
        return qc

    # Choose half the possible input strings
    on_states = np.random.choice(
        range(2**num_qubits),  # numbers to sample from
        2**num_qubits // 2,  # number of samples
        replace=False,  # makes sure states are only sampled once
    )

    def add_cx(qc, bit_string):
        for qubit, bit in enumerate(reversed(bit_string)):
            if bit == "1":
                qc.x(qubit)
        return qc

    for state in on_states:
        qc.barrier()  # Barriers are added to help visualize how the functions are created.
        qc = add_cx(qc, f"{state:0b}")
        qc.mcx(list(range(num_qubits)), num_qubits)
        qc = add_cx(qc, f"{state:0b}")

    qc.barrier()

    return qc

Possiamo mostrare l'implementazione del circuito quantistico della porta di interrogazione utilizzando il metodo draw come di consueto.

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

Output:

Output of the previous code cell

Definiamo poi una funzione che crea il circuito di Deutsch-Jozsa, prendendo come argomento un'implementazione del circuito quantistico di un query gate.

def compile_circuit(function: QuantumCircuit):
    # Compiles a circuit for use in the Deutsch-Jozsa algorithm.

    n = function.num_qubits - 1
    qc = QuantumCircuit(n + 1, n)
    qc.x(n)
    qc.h(range(n + 1))
    qc.compose(function, inplace=True)
    qc.h(range(n))
    qc.measure(range(n), range(n))
    return qc

Infine, viene definita una funzione che esegue una volta il circuito Deutsch-Jozsa.

def dj_algorithm(function: QuantumCircuit):
    # Determine if a function is constant or balanced.

    qc = compile_circuit(function)

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

Possiamo testare la nostra implementazione scegliendo una funzione a caso, visualizzando l'implementazione del circuito quantistico di una porta di interrogazione per questa funzione e poi eseguendo l'algoritmo di Deutsch-Jozsa su quella funzione.

f = dj_query(3)
display(f.draw("mpl"))
display(dj_algorithm(f))

Output:

Output of the previous code cell
'balanced'

Il problema di Bernstein-Vazirani

Successivamente, discuteremo un problema noto come problema di Bernstein-Vazirani. È anche chiamato problema del campionamento di Fourier, sebbene esistano formulazioni più generali di questo problema che vanno anche sotto questo nome.

Per prima cosa, introduciamo alcune notazioni. Per due stringhe binarie qualsiasi x=xn1x0x = x_{n-1} \cdots x_0 e y=yn1y0y = y_{n-1}\cdots y_0 di lunghezza n,n, definiamo

xy=xn1yn1x0y0.x \cdot y = x_{n-1} y_{n-1} \oplus \cdots \oplus x_0 y_0.

Questa operazione viene chiamata prodotto binario dei punti. Un modo alternativo per definirlo è il seguente.

xy={1xn1yn1++x0y0 is odd0xn1yn1++x0y0 is evenx \cdot y = \begin{cases} 1 & x_{{n-1}} y_{n-1} + \cdots + x_0 y_0 \text{ is odd}\\[0.5mm] 0 & x_{{n-1}} y_{n-1} + \cdots + x_0 y_0 \text{ is even} \end{cases}

Si noti che si tratta di un'operazione simmetrica, il che significa che il risultato non cambia se si scambiano xx e y,y,, quindi siamo liberi di farlo ogni volta che è conveniente. A volte è utile pensare al prodotto binario dei punti xyx \cdot y come alla parità dei bit di xx nelle posizioni in cui la stringa yy ha un 1,1, o, equivalentemente, alla parità dei bit di yy nelle posizioni in cui la stringa xx ha un 1.1.

Con questa notazione in mano possiamo ora definire il problema di Bernstein-Vazirani.

Bernstein-Vazirani problem

Input: una funzione f:{0,1}n{0,1}f:\{0,1\}^n\rightarrow\{0,1\} \ Promessa: esiste una stringa binaria s=sn1s0s = s_{n-1} \cdots s_0 per la quale f(x)=sxf(x) = s\cdot x per tutte le xΣnx\in\Sigma^n \ Uscita: la stringa ss

In realtà non abbiamo bisogno di un nuovo algoritmo quantistico per questo problema; l'algoritmo di Deutsch-Jozsa lo risolve. Per chiarezza, chiamiamo il circuito quantistico di cui sopra, che non include la fase classica di post-elaborazione del calcolo dell'OR, circuito Deutsch-Jozsa.

Analisi dell'algoritmo

Per analizzare come funziona il circuito di Deutsch-Jozsa per una funzione che soddisfa la promessa del problema di Bernstein-Vazirani, inizieremo con una rapida osservazione. Utilizzando il prodotto binario dei punti, possiamo descrivere alternativamente l'azione delle porte di Hadamard di nn sugli stati base standard dei qubit di nn come segue.

Hnx=12nyΣn(1)xyyH^{\otimes n} \vert x \rangle = \frac{1}{\sqrt{2^n}} \sum_{y\in\Sigma^n} (-1)^{x\cdot y} \vert y\rangle

Analogamente a quanto abbiamo visto analizzando l'algoritmo di Deutsch, questo è dovuto al fatto che il valore (1)k(-1)^k per qualsiasi intero kk dipende solo dal fatto che kk sia pari o dispari.

Passando al circuito di Deutsch-Jozsa, dopo che è stato eseguito il primo strato di porte di Hadamard, lo stato dei qubit di n+1n+1 è

12nxΣnx.\vert - \rangle \otimes \frac{1}{\sqrt{2^n}} \sum_{x \in \Sigma^n} \vert x \rangle.

Viene quindi eseguito il gate di interrogazione, che (attraverso il fenomeno del contraccolpo di fase) trasforma lo stato in

12nxΣn(1)f(x)x.\vert - \rangle \otimes \frac{1}{\sqrt{2^n}} \sum_{x \in \Sigma^n} (-1)^{f(x)} \vert x \rangle.

Utilizzando la nostra formula per l'azione di uno strato di porte di Hadamard, vediamo che il secondo strato di porte di Hadamard trasforma poi questo stato in

12nxΣnyΣn(1)f(x)+xyy.\vert - \rangle \otimes \frac{1}{2^n} \sum_{x \in \Sigma^n} \sum_{y \in \Sigma^n} (-1)^{f(x) + x \cdot y} \vert y \rangle.

Ora possiamo fare alcune semplificazioni, nell'esponente di 1-1 all'interno della somma. Ci è stato promesso che f(x)=sxf(x) = s\cdot x per qualche stringa s=sn1s0,s = s_{n-1} \cdots s_0, in modo da poter esprimere lo stato come

12nxΣnyΣn(1)sx+xyy.\vert - \rangle \otimes \frac{1}{2^n} \sum_{x \in \Sigma^n} \sum_{y \in \Sigma^n} (-1)^{s\cdot x + x \cdot y} \vert y \rangle.

Poiché sxs\cdot x e xyx\cdot y sono valori binari, possiamo sostituire l'addizione con l'OR esclusivo - sempre perché l'unica cosa che conta per un intero nell'esponente di 1-1 è che sia pari o dispari. Sfruttando la simmetria del prodotto binario dei punti, si ottiene questa espressione per lo stato:

12nxΣnyΣn(1)(sx)(yx)y.\vert - \rangle \otimes \frac{1}{2^n} \sum_{x \in \Sigma^n} \sum_{y \in \Sigma^n} (-1)^{(s\cdot x) \oplus (y \cdot x)} \vert y \rangle.

(Le parentesi sono state aggiunte per chiarezza, anche se in realtà non sono necessarie perché è convenzionale trattare il prodotto binario dei punti come se avesse una precedenza maggiore rispetto all'OR esclusivo)

A questo punto utilizzeremo la seguente formula.

(sx)(yx)=(sy)x(s\cdot x) \oplus (y \cdot x) = (s \oplus y) \cdot x

Possiamo ottenere la formula attraverso una formula simile per i bit,

(ac)(bc)=(ab)c,(a c) \oplus (b c) = (a \oplus b) c,

insieme a un'espansione del prodotto binario dei punti e del bitwise exclusive-OR:

(sx)(yx)=(sn1xn1)(s0x0)(yn1xn1)(y0x0)=(sn1yn1)xn1(s0y0)x0=(sy)x\begin{aligned} (s\cdot x) \oplus (y \cdot x) & = (s_{n-1} x_{n-1}) \oplus \cdots \oplus (s_{0} x_{0}) \oplus (y_{n-1} x_{n-1}) \oplus \cdots \oplus (y_{0} x_{0}) \\ & = (s_{n-1} \oplus y_{n-1}) x_{n-1} \oplus \cdots \oplus (s_{0} \oplus y_{0}) x_{0} \\ & = (s \oplus y) \cdot x \end{aligned}

Questo ci permette di esprimere lo stato del circuito immediatamente prima delle misure in questo modo:

12nxΣnyΣn(1)(sy)xy.\vert - \rangle \otimes \frac{1}{2^n} \sum_{x \in \Sigma^n} \sum_{y \in \Sigma^n} (-1)^{(s\oplus y)\cdot x} \vert y \rangle.

Il passo finale consiste nell'utilizzare un'altra formula, che funziona per ogni stringa binaria z=zn1z0.z = z_{n-1}\cdots z_0.

12nxΣn(1)zx={1if z=0n0if z0n\frac{1}{2^n} \sum_{x \in \Sigma^n} (-1)^{z \cdot x} = \begin{cases} 1 & \text{if $z = 0^n$}\\ 0 & \text{if $z\neq 0^n$} \end{cases}

Qui usiamo una semplice notazione per le stringhe che useremo più volte nel corso della lezione: 0n0^n è la stringa di lunghezza pari a zero n.n.

Un modo semplice per dimostrare che questa formula funziona è considerare i due casi separatamente. Se z=0n,z = 0^n, allora zx=0z\cdot x = 0 per ogni stringa xΣn,x\in\Sigma^n, quindi il valore di ogni termine della somma è 1,1, e si ottiene 11 sommando e dividendo per 2n.2^n. D'altra parte, se uno qualsiasi dei bit di zz è uguale a 1,1, allora il prodotto binario dei punti zxz\cdot x è uguale a 00 per esattamente la metà delle scelte possibili per xΣnx\in\Sigma^n e 11 per l'altra metà - perché il valore del prodotto binario dei punti zxz\cdot x si capovolge (da 00 a 11 o da 11 a 00 ) se capovolgiamo un qualsiasi bit di xx in una posizione in cui zz ha una 1.1.

Se ora applichiamo questa formula per semplificare lo stato del circuito prima delle misure, otteniamo

12nxΣnyΣn(1)(sy)xy=s,\vert - \rangle \otimes \frac{1}{2^n} \sum_{x \in \Sigma^n} \sum_{y \in \Sigma^n} (-1)^{(s\oplus y)\cdot x} \vert y \rangle = \vert - \rangle \otimes \vert s \rangle,

perché sy=0ns\oplus y = 0^n se e solo se y=s.y = s. Pertanto, le misure rivelano proprio la stringa ss che stiamo cercando.

Difficoltà classica

Mentre il circuito Deutsch-Jozsa risolve il problema di Bernstein-Vazirani con una sola interrogazione, qualsiasi algoritmo di interrogazione classico deve effettuare almeno nn interrogazioni per risolvere questo problema.

Si può ragionare attraverso un cosiddetto argomento di teoria dell'informazione, che in questo caso è molto semplice. Ogni interrogazione classica rivela un singolo bit di informazione sulla soluzione, e ci sono nn bit di informazione che devono essere scoperti, quindi sono necessarie almeno nn interrogazioni.

È infatti possibile risolvere il problema di Bernstein-Vazirani in modo classico, interrogando la funzione su ciascuna delle stringhe nn che hanno un singolo 1,1, in ogni possibile posizione, e 00 per tutti gli altri bit, che rivela i bit di ss uno alla volta. Pertanto, il vantaggio degli algoritmi quantistici rispetto a quelli classici per questo problema è 11 query rispetto a nn query.


Bernstein-Vazirani con Qiskit

Abbiamo già implementato il circuito di Deutsch-Jozsa sopra, e qui lo useremo per risolvere il problema di Bernstein-Vazirani. Per prima cosa definiremo una funzione che implementa una porta di interrogazione per il problema di Bernstein-Vazirani, data una qualsiasi stringa binaria s.s.

def bv_query(s):
    # Create a quantum circuit implementing a query gate for the
    # Bernstein-Vazirani problem.

    qc = QuantumCircuit(len(s) + 1)
    for index, bit in enumerate(reversed(s)):
        if bit == "1":
            qc.cx(index, len(s))
    return qc


display(bv_query("1011").draw(output="mpl"))

Output:

Output of the previous code cell

Ora possiamo creare una funzione che esegua il circuito Deutsch-Jozsa sulla funzione, utilizzando la funzione compile_circuit definita in precedenza.

def bv_algorithm(function: QuantumCircuit):
    qc = compile_circuit(function)
    result = AerSimulator().run(qc, shots=1, memory=True).result()
    return result.get_memory()[0]


display(bv_algorithm(bv_query("1011")))

Output:

'1011'

Osservazione sulla nomenclatura

Nel contesto del problema di Bernstein-Vazirani, è comune che l'algoritmo di Deutsch-Jozsa sia indicato come "algoritmo di Bernstein-Vazirani" Questo è leggermente fuorviante, perché l'algoritmo è l'algoritmo di Deutsch-Jozsa, come Bernstein e Vazirani hanno detto chiaramente nel loro lavoro.

Dopo aver dimostrato che l'algoritmo di Deutsch-Jozsa risolve il problema di Bernstein-Vazirani (come si è detto), Bernstein e Vazirani hanno definito un problema molto più complicato, noto come problema di campionamento ricorsivo di Fourier. Si tratta di un problema altamente congegnato in cui le soluzioni alle diverse istanze del problema sbloccano effettivamente nuovi livelli del problema disposti in una struttura ad albero. Il problema di Bernstein-Vazirani è essenzialmente solo il caso base di questo problema più complicato.

Il problema del campionamento ricorsivo di Fourier è stato il primo esempio conosciuto di problema di interrogazione in cui gli algoritmi quantistici hanno un vantaggio cosiddetto super-polinomiale rispetto agli algoritmi probabilistici, superando così il vantaggio dei quanti rispetto ai classici offerto dall'algoritmo di Deutsch-Jozsa. Intuitivamente, la versione ricorsiva del problema amplifica il vantaggio di 11 rispetto a nn degli algoritmi quantistici a qualcosa di molto più grande.

L'aspetto più impegnativo dell'analisi matematica che stabilisce questo vantaggio è dimostrare che gli algoritmi di interrogazione classici non possono risolvere il problema senza effettuare molte interrogazioni. Questo è abbastanza tipico; per molti problemi può essere molto difficile escludere approcci classici creativi che li risolvano in modo efficiente.

Il problema di Simon, e l'algoritmo per esso descritto nella prossima sezione, fornisce un esempio molto più semplice di un vantaggio super-polinomiale (e, di fatto, esponenziale) degli algoritmi quantistici rispetto a quelli classici, e per questo motivo il problema del campionamento ricorsivo di Fourier viene discusso meno spesso. Si tratta comunque di un interessante problema computazionale a sé stante.

Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.