INFORMATICA - QUANTUM COMPUTING - OPERATORS

Marzo 2024

1. Le porte quantistiche e gli operatori

Nella pagina precedente abbiamo visto la forma vettoriale di |0> e |1>, ora è necessario inquadrare, in questo ambito, come sono viste le porte quantistiche. In breve, considerando come sempre solo gli aspetti informatici di programmazione e lasciando la parte matematica al minimo indispensabile, le porte quantistiche come quella di Hadarmard [H] e [CNOT], sono matrici dotate di particolari caratteristiche. Ad esempio la [H] è la matrice seguente:







mentre la [CNOT]:










Andando quindi a considerare il circuito che segue, già analizzato nelle pagine precedenti:

come agirà l'operatore [H]? Basterà svolgere il prodotto righe per colonne della matrice [H] di cui sopra e del vettore di ingresso, ossia |0>:

Questo risultato, già presentato in quella pagina evidenzia molto semplicemente il discorso della sovrapposizione degli stati, ossia, si parte da uno stato |0> di ingresso e si arriva, dopo la porta [H], ad uno stato d'uscita che è una combinazione bilanciata di |0> e |1>.

Per la [CNOT] il discorso è identico ma stavolta si deve operare su 2 qbit, per cui partendo dal circuito (anch'esso già visto):

si può svolgere il prodotto righe per colonne della matrice [CNOT] con il prodotto tensoriale dei due qbit di ingresso (vds pagina precedente) ottenendo:

dove si può verificare che il risultato dell'applicazione della porta [CNOT] a |00> è proprio |00> ossia non ci sono modifiche. Si lascia al lettore di verificare che applicando [CNOT] a |10> il discorso cambia notevolmente (il qbit di controllo, infatti, attiva la [CNOT] in questo caso, invertendo il secondo qbit da cui si otterrà |11>).

Quali sono le caratteristiche che hanno le matrici degli operatori che si possono usare nel quantum computing? Molto brevemente, senza estendere eccessivamente il discorso, se si considera la matrice trasposta (si scambiano gli elementi tra righe e colonne) coniugata (i termini complessi cambiano segno nella parte immaginaria), il prodotto tra la matrice dell'operatore e la sua trasposta coniugata deve dare la matrice unitaria I (tutti 1 sulla diagonale e restanti elementi 0). Non è difficile fare il calcolo con [H] e [CNOT] per verificare questa proprietà ([H] e [CNOT] sono matrici unitarie). In ogni caso, per il programmatore questo fatto ha un peso relativo dato che le porte quantistiche sono fornite come primitive dal sistema che consente di programmare.

Un aspetto molto importante è che qualsiasi programma per macchine quantistiche, quale "combinazione" di porte (operatori) unitari, realizza un operatore unitario e quindi, in definitiva, una matrice numerica con certe caratteristiche. Lo schema circuitale è solo per ricordarci le funzioni delle porte, altrimenti, di fatto, staremmo semplicemente progettando delle matrici... questo mi ricorda molto quando programmavo in assembler senza compilatore; scritto il programma su carta lo convertivo in stringhe di bit per poi memorizzarle in aree di memoria e darle in pasto ad una specifica CPU. Nei computer quantistici, invece, si può pensare, semplificando, che blocchi di matrici e vettori, fatti di numeri complessi, vanno in pasto a delle QPU. Non cambia poi così tanto... :-)

Prima di passare ad altro, vorrei riprendere l'assurdo logico della porta di Hadamard già visto in quella pagina:

Seguendo il circuito con il prodotto righe per colonne non è difficile vedere che [H][H]|0> = |0> ossia si conferma che applicando 2 volte la porta [H] si torna allo stato quantistico |0> di partenza. Invece andando a misurare [H]|0> si trova un valore casuale perchè [H]|0> è una sovrapposizione bilanciata di |0> ed |1> (vds sopra). Quindi, come già sottolineato, [H] sembra comportarsi come un randomizzatore in certe circostanze ma in altre fornisce un valore deterministico unico.

2. Clonare uno stato quantistico

Avendo introdotto gli operatori si può ora parlare di un altro aspetto davvero peculiare dei computer quantistici, l'impossibilità di clonare i qbit in un qualsiasi registro quantistico. Per i programmatori l'assegnazione q[1] := q[0] è un punto fermo delle possibilità tecniche e viene sfruttato continuamente nella realizzazione di un software: il valore puntato dal registro q all'indirizzo 0 viene copiato nella cella di memoria puntata dallo stesso registro q all'indirizzo 1. A livello di CPU classiche l'assegnazione viene realizzata mediante dei buffer particolari, ossia dei sistemi che splittano la linea di comunicazione a livello di BUS. Segue un esempio grafico (le linee sono doppie perchè indicano bit classici):

Facciamoci una domanda davvero importante: i buffer disaccoppiano la X di sopra e le tre X (clonate) di sotto ma fino a che punto la X di sopra è identica alle tre X di sotto? La risposta è semplice: a livello elettrico di segnale ogni X è differente dalle altre, ma a livello digitale (di interpretazione della CPU) tutti tali segnali, sebbene leggermente diversi tra loro vengono compresi (interpretati) dalla CPU allo stesso modo quale contenuto informativo (bit classico).

Nel mondo quantistico scendiamo a livello di segnale elettrico (microscopico) e non rimaniamo a livello del digitale (che è un mondo macroscopico, accessibile ad una misura diretta ed inequivocabile a meno di malfunzionamenti della macchina). Ogni qbit di un registro, di fatto, è un'onda su molteplici dimensioni (non fatevi esplodere la testa, voglio solo dire che è un qualcosa che cambia continuamente su tante variabili), inoltre è particolarmente "suscettibile" quando si interagisce con essa, tende a cambiare repentinamente. Di fatti, vedremo adesso che clonare i qbit è possibile solo in pochi casi veramente banali.

Partiremo considerando l'idea macroscopica più semplice, ossia l'uso di una misura e di un buffer parimenti a quanto si fa nel mondo digitale classico:

si considera quindi un qbit |X> e la sua misura X; dato che X è un bit classico si può applicare un buffer e clonarlo come visto prima. Il problema fondamentale è che X (la misura) è profondamente diverso da |X> (lo stato quantistico), in generale, infatti, se |X> = a|0> + b|1> dopo la misura |X> si dimostra che collassa su |0> o su |1> con probabilità rispettivamente a2 o b2, ossia in X l'informazione relativa ad a e b è persa. Lo schema appena visto, quindi, funziona solo nel caso banale che |X> = |0> (a=1 e b=0) oppure |X> = |1> (a=0 e b=1), mentre per le sovrapposizioni (caso più comune e ricco di informazioni) X non si può ritenere un clone di |X>.

Facciamo ora un tentativo più complicato (che ci servirà anche come esercizio di programmazione), proviamo ad usare una [CNOT] inserendo come qbit controllato uno |0>:

Non è difficile considerare che la [CNOT], in base a come funziona, sembra ricopiare il qbit di controllo |X> infatti:
se |X> = |0> si ha |Y> = |0> = |X>,
così come:
se |X> = |1> si ha |Y> = |1> = |X>.
Rimane da verificare cosa accade per |X> combinazione lineare di |0> e |1>. Basterà applicare la matrice della [CNOT] svolgendo il prodotto righe per colonne come segue:

nell'ipotesi che il qbit d'uscita |Y> sia il clone perfetto di |X> si avrebbe:

da cui:

ma questo è un assurdo rispetto alle ipotesi iniziali fatte che sia alfa che beta siano diversi da zero (altrimenti ricadiamo nel caso banale).

Per chiudere facciamo il caso generico di considerare un operatore che risultasse un clonatore perfetto di |X> su |Y>:

Esso prenderebbe in ingresso due stati quantistici diversi (di cui uno |X>) e su due qbit differenti in uscita restituirebbe lo stesso stato quantistico |X>. La matrice dell'operatore deve essere il prodotto tensoriale tra la matrice identità I (che prende in ingressi |X> e lo restituisce identico in uscita sullo stesso qbit del registro) ed un'altra matrice incognita che opererebbe la clonazione. Proviamo quindi a calcolare i 4 valori della matrice incognita:

sulla falsa riga di prima, ipotizzando che il clonatore funzioni:

da cui si definisce un sistema di equazioni le cui incognite sono proprio i 4 valori della matrice incognita:

non è difficile vedere che questo sistema non ammette soluzioni (non banali) in quanto il determinante è nullo:

La conclusione è che la matrice delle incognite che permette all'operatore di clonare |X> non può esistere. Questo risultato che abbiamo studiato con vari esempi è spesso indicato come no-cloning theorem e risulta fondamentale per le comunicazioni quantistiche. Sancisce infatti l'impossibilità di intercettare tali comunicazioni senza alterare definitivamente le informazioni che passano, la base delle comunicazioni quantistiche super-sicure, ma vedremo questo fatto in dettaglio successivamente.

3. Conclusioni

I software quantistici sono praticamente delle matrici e le vecchie care assegnazioni tra variabili non si possono fare! Tutto questo è destabilizzante ma ci si abitua presto. Le assegnazioni iniziali (a sinistra) nel circuito quantistico sono sempre con |0> e |1> per i quali abbiamo visto che il caso è banale e si può fare. Per il resto c'è continuamente bisogno di nuovi qbit dato che il riutilizzo con valori diversi è praticamente impossibile. Tale mancanza di passaggi di valore tra i qbit del registro creano però un'altro grosso intoppo rispetto alla programmazione classica: non ci sono loop quantistici! In termini circuitali non possono esserci feedback di nessun tipo, il circuito è forward-only, va solo avanti... Posso sicuramente asserire che questo fatto è stato per me estremamente difficile da accettare e aggirare nel processo di programmazione. Tutto comunque, ripeto, è solo questione di abitudine :-)))