INFORMATICA - QUANTUM COMPUTING
PQRNG

Febbraio 2026

1. PQRNG

Come introdotto nelle pagine sui Quantum Random Number Generator e sul hypercomputing i generatori di numeri casuali basati su effetti quantistici realizzano flussi binari "realmente" casuali partendo da effetti quantistici e quindi non deterministici di principio.

Nonostante ciò è spesso necessario generare delle sequenze pseudo casuali partendo da un valore (seed). Tali sequenze devono risultare deterministiche a partire dal seed (stesso seed - stessa sequenza) ma pseudo casuali nel senso delle proprietà statistiche e talvolta della predicibilità del valore successivo a partire da quello precedente.

Ad esempio, nel testo Understanding Cryptography (Springer 2024 - Second Edition), specificamente per la crittografia, viene descritta la caratteristica da associare ad una particolare classe di generatori pseudo random detti CSPRNG (Criptographically Secure Pseudo Random Number Generator). In pratica i CSPRNG sono PRNG per i quali data una sequenza di output generata x1,x2,...xm..., non è computazionalmente fattibile (o comunque è estremamente difficile) determinare la prosecuzione della stessa xm+1,xm+2,...

PRNG e CSPRNG sono importanti in una serie di applicazioni in cybersecurity ed è interessante notare che la principale caratteristica per cui sono impiegati non è la casualità (caratteristica per la quale i QRNG sono insuperabili), ma piuttosto il determinismo della sequenza generata partendo dal seed.

Nella considerazione che i PRNG in generale sono dei software, in questo lavoro considereremo la realizzazione di uno Pseudo Quantum Random Number Generator (PQRNG), ossia un software quantistico su computer quantistico general-purpose (gate-based) che dato un seed in forma binaria, genera una sequenza pseudo-random di numeri interi in forma sempre binaria. Dato che il software in questione è su sistema gate-based esso consisterà in un circuito quantistico che utilizza porte quantistiche standard. Alcune di queste porte sono state introdotte nei lavori precedenti Quantum Program 1 e Quantum Registers. Nei prossimi paragrafi, introdurremo altri esempi di circuiti e porte quantistiche per consentire la realizzazione specifica di una funzione PQRNG.

Tutto il software quantistico è stato realizzato tramite la libreria open source CirQ di Google (richiamata in python) ed è liberamente disponibile (come lo sono tutti i miei progetti software) su github.com/mmattiucci2024/pqrng. CirQ è anche un emulatore quantistico che si può installare sul proprio PC per prove di programmazione che coinvolgono pochi qbit. Ciò non toglie che tale libreria si può anche usare per programmare i computer quantistici o ibridi di Google sul cloud.


2. Premessa sulle porte quantistiche


2.1 La matrice della CNOT

Abbiamo già visto che le porte quantistiche agiscono su dei registri di quantum bit(s) svolgendo determinate funzioni. Ad esempio la CNOT (controlled-NOT) agisce su un registro di 2 qbit invertendo uno dei due sul comando dell'altro (vds Quantum Program 1).

Abbiamo anche visto nella pagina Operators che la funzione svolta da una porta quantistica può sempre essere descritta da una matrice di numeri complessi con particolari caratteristiche (che ora non approfondiamo), ad esempio per la CNOT abbiamo la seguente matrice e il seguente schema nel formalismo ASCII di CirQ:

$$ CNOT = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{pmatrix} $$
q0: ───@───
       │   
q1: ───X───

dove il qbit |q0> controlla l'inversione e il qbit |q1> è soggetto all'inversione. Infatti, ipotizzando genericamente:
|q0> = a|0>+b|1> = (a,b)T
|q1> = c|0>+d|1> = (c,d)T
(dove T è l'operatore di trasposizione, si tratta quindi di vettori colonna), si avrebbe il tensore corrispondente sul registro a due dimensioni:
|q0> ⊗ |q1> = (a(c,d),b(c,d))T = (ac,ad,bc,bd)T.

Applicare la porta CNOT a |q0> ⊗ |q1> significa moltiplicare, righe per colonne, la matrice CNOT per il vettore |q0> ⊗ |q1> ottenendo:
CNOT (|q0> ⊗ |q1>) = (ac,ad,bd,bc)T.

Se quindi ipotizziamo q0 =|0>, ossia a = 1 e b = 0, il risultato è (c,d,0,0)T, il quale, è esprimibile come prodotto tensoriale:

(c,d,0,0) = (1(c,d),0(0,0))T = (1,0)T ⊗ (c,d)T = |0> ⊗ |q1>

per cui il registro d'uscita per |q0> rimane |0> come da ipotesi e per |q1> rimane |q1>.

Ora, ipotizziamo q0 =|1>, ossia a = 0 e b = 1, il risultato della porta è (0,0,d,c)T, il quale, è esprimibile come prodotto tensoriale:

(0,0,d,c) = (0(0,0),1(d,c))T = (0,1)T ⊗ (d,c)T
= |1> ⊗ NOT(|q1>)

per cui il registro d'uscita per |q0> rimane |1> come da ipotesi e per |q1> si ha l'inversione dei termini c e d di |q1> che passa da c|0>+d|1> a d|0>+c|1> (attenzione che in termini di probabilità l'inversione dei termini corrisponde all'inversione delle probabilità per il qbit di essere osservato/misurato come 0 o 1).

Facciamo ora un altro passo avanti considerando sempre la CNOT ma con il controllo invertito, ossia il circuito che segue:

q0: ───X───
       │   
q1: ───@───

come si può vedere stavolta |q1> controlla l'inversione di |q0>. In tal caso la matrice cambia come segue:

$$ CNOT = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \end{pmatrix} $$

per la quale possono essere fatte considerazioni matematiche simili alle precedenti che, però, conducono ad avere che per q1=|1> si ha l'inversione dei termini a e b di |q0>.


2.2 Per i più appassionati...

Se vi chiedete come si costruiscono le matrici delle porte quantistiche in maniera correlata alle loro funzioni, il meccanismo matematico non è complicato anche se non sempre tali matrici sono relative a porte realizzabili poi nella realtà. La CNOT è una porta quantistica di base che nella realtà può essere costruita per cui analizzeremo come ottenere la sua matrice essendo sicuri che rappresenta qualcosa di reale.
Facendo riferimento al pragmatico testo "Quantum Computing & Information A scaffolding approach (2024 Polaris QCI Publishing), si parte dalla definizione classica:
|0> = (1,0)T
|1> = (0,1)T
per poi passare ai prodotti tensoriali per un registro a due dimensioni:
|00> = |0> ⊗ |0> = (1,0,0,0)T
|01> = |0> ⊗ |1> = (0,1,0,0)T
|10> = |1> ⊗ |0> = (0,0,1,0)T
|11> = |1> ⊗ |1> = (0,0,0,1)T

Si realizza, a questo punto, una sorta di tabella della verità, ad esempio la porta CNOT con controllo su |q0> (la prima che abbiamo visto):

q0 q1 q0
uscita
q1
uscita
0 0 0 0
0 1 0 1
1 0 1 1
1 1 1 0

dove la 3^ e 4^ colonna rappresentano l'uscita deterministica della porta che si desidera (ossia |q1> invertito solo quando |q0>=|1>).

Si può dimostrare che la matrice della porta relativa alla tabella considerata è la seguente somma matriciale (procedendo riga per riga):
CNOT = |00><00| + |01><01| + |10><11| + |11><10|
in questo caso semplificato, non essendoci coinvolti numeri complessi, la notazione di Dirac <__| corrisponde alla semplice trasposizione del vettore colonna |__>, quindi:
CNOT =
(1,0,0,0)T(1,0,0,0) +
(0,1,0,0)T(0,1,0,0) +
(0,0,1,0)T(0,0,0,1) +
(0,0,0,1)T(0,0,1,0) =
ossia la somma delle seguenti 4 matrici quadrate:

$$ \begin{aligned} \text{} &= \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \end{pmatrix} + \begin{pmatrix} 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \end{pmatrix} \\[1em] &+ \begin{pmatrix} 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 \end{pmatrix} + \begin{pmatrix} 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \end{pmatrix} \end{aligned} $$
che porta proprio alla matrice indicata nel par.2.1:
$$ \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{pmatrix} $$

Per la matrice della CNOT a controllo invertito si può procedere allo stesso modo, ma si lascia la procedura al lettore (se ci sono problemi semplicemente contattatemi per email e integrerò questo studio anche con essa).


3. Un circuito quantistico particolare

Consideriamo ora il seguente circuito quantistico usando il formalismo ASCII di CirQ:

q0: ───@───X───@───
       │   │   │
q1: ───X───@───X───

in definitiva si tratta di 3 porte CNOT in serie ma con quella in mezzo a controlli invertiti. Si può schematizzare il circuito come segue:

Dato che conosciamo dal par.2 le 3 matrici delle 3 porte, facendo il prodotto riga per colonna di esse è possibile determinare la matrice che caratterizza l'intero circuito:

$$ \begin{aligned} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 1 \end{pmatrix} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \end{pmatrix} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 1 \end{pmatrix} = \end{aligned} $$

ottenendo:

$$ SWAP = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} $$

Consideriamo ora un generico input a questo circuito:
|q0> = a|0>+b|1> = (a,b)T
|q1> = c|0>+d|1> = (c,d)T
e vediamo cosa accade in uscita. Il tensore di input sarà, come già visto
|q0> ⊗ |q1> = (ac,ad,bc,bd)T
e applicandola alla matrice del circuito appena ottenuto si ha:

$$ \begin{aligned} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} ac \\ ad \\ bc \\ bd \end{pmatrix} &= \begin{pmatrix} ac \\ bc \\ ad \\ bd \end{pmatrix} = \begin{pmatrix} c(a,b)^T \\ d(a,b)^T \end{pmatrix} = \end{aligned} $$
$$ \begin{aligned} = \begin{pmatrix} c \\ d \end{pmatrix} \otimes \begin{pmatrix} a \\ b \end{pmatrix} = |q_1\rangle \otimes |q_0\rangle \end{aligned} $$

quindi, all'uscita del circuito |q0> e |q1> si presentano permutati di posizione tra loro.


3.1 La porta SWAP

La funzione di questo circuito viene, in letteratura, indicata con SWAP, un permutatore a due qbit illustrato di seguito sempre nel formalismo di CirQ:

q0: ───x─── q1
       │   
q1: ───x─── q0

E' interessante osservare che nella pagina No cloning ho evidenziato come un qbit non può essere di principio clonato, ossia non si può realizzare una porta quantistica di fan-out che da una linea corrispondente ad 1 qbit ne determini diverse in uscita che ne sono cloni. Ciò nonostante è possibile, in un certo senso, spostare i qbit tra loro con la porta di SWAP.

La SWAP ovviamente può essere realizzata nella realtà dato che è una combinazione di CNOT la quale è una porta base. Da questo assumiamo che i qbit non sono clonabili ma sono permutabili tra loro su più linee. Tali caratteristiche sono fondamentali per la costruzione di diversi algoritmi quantistici in molti settori di applicazione.


3.2 Uno shift-register quantistico

Quale semplice esercizio (che ci servirà nel prosieguo di questo studio), partendo da due SWAP realizziamo ora il circuito che segue su 3 qbit:

q0: ───x─────── q1
       │   
q1: ───x───x─── q2
           │
q2: ───────x─── q0

Anche intuitivamente (e quindi senza ricorrere per forza al calcolo matriciale) si può capire che la prima SWAP scambia |q0> con |q1> e la seconda |q1> con |q2> determinando, di fatto, uno shift register con circolarità sui 3 qbit. Se ovviamente procediamo al calcolo tensoriale su 3 qbit e poi a quello matriciale questo fatto viene confermato. Nel caso farete questa prova vedrete che all'aumentare dei qbit gestire il prodotto tensoriale è sempre più oneroso dato che l'aumento dei calcoli (anche se semplici) è esponenziale.


4. Il circuito del PQRNG

Abbiamo finalmente tutti gli strumenti per procedere alla costruzione del PQRNG. Consideriamo per semplicità un registro a soli 3 qbit e impostiamo il circuito che segue:

q0: ───X───x───────[M(q0)] 
       │   │
q1: ───@───x───x───[M(q1)]
               │
q2: ───────────x───[M(q2)] 

dove M() è la funzione di misura (che fa collassare i valori della corrispondente linea quantistica del registro a 0 o a 1). Supponiamo di partire con un input di tutti |0>: la CNOT non si attiva e i due permutatori neanche, si ottiene quindi in uscita |0> per tutti e quindi dalla misura il registro mostra 000.

Le misure M(q0),M(q1) e M(q2), essendo valori collassati reali e non stati quantistici, possono essere gestite da elaboratori classici. Nella considerazione che le macchine quantistiche (i circuiti) non consentono nè fan-out e nemmeno loop o feedback, impiegheremo una computazione ibrida (classica/quantistica) per implementare un loop. I valori misurati M(q0),M(q1) e M(q2) saranno quindi impiegati da un elaboratore classico per costruire un nuovo circuito quantistico che in ingresso ha delle nuove porte destinate a impostare |000> sapendo che |q0>, |q1> e |q2> sono comunque inizialmente |0>. La porta di setup per l'input a |0> è la porta identità I costituita, come noto, da tutti 1 sulla diagonale principale e 0 altrove:

q0: ───I───X───x───────[M(q0)] 
           │   │
q1: ───I───@───x───x───[M(q1)]
                   │
q2: ───I───────────x───[M(q2)] 

Matrice I (Identity)
I =
1 0
0 1
Lascia lo stato invariato
Matrice X (Pauli-X)
X =
0 1
1 0
Scambia |0⟩ e |1⟩

il loop ibrido che parte da 000 determina quindi una sequenza stabile su 000:

000
↺


Partendo invece da 001, si ottiene in uscita la misura 010 che determina il nuovo circuito quantistico:

q0: ───I───X───x───────[M(q0)] 
           │   │
q1: ───X───@───x───x───[M(q1)]
                   │
q2: ───I───────────x───[M(q2)] 

dove, come si può vedere, il valore |1> per |q1> è stato impostato mediante una porta NOT (indicata con X nel formalismo di CirQ). Il nuovo valore che si misurerà in uscita è ora 101, che porterà, nel loop ibrido, alla costruzione di un nuovo circuito e così avanti.

Si può vedere, con un poco di pazienza (facendo girare il mio software github.com/mmattiucci2024/pqrng) che la sequenza totale è circolare ed è la seguente:

001
→
010
→
101
→
011
→
111
→
110
→
100
↺


Allargando il registro a 4 qbit:

q0: ──────X───x───────────[M(q0)] 
          │   │
q1: ──────│───x───x───────[M(q1)]
          │       │
q2: ──────@───────x───x───[M(q2)] 
                      │
q3: ──────────────────x───[M(q3)] 

si ha nuovamente un loop stabile su 0000. Mentre si identificano diverse sequenze circolari:

0000
↺


0001
→
0010
→
0101
→
1010
→
0100
→
1000
↺


0011
→
0111
→
1111
→
1110
→
1100
→
1001
↺


0110
→
1101
→
1011
↺


Proseguendo, all'aumentare del numero di qbit, aumentano anche numero e lunghezza dei cicli.


4.1 Struttura generalizzata del PQRNG

Il PQRNG è quindi strutturato nelle seguenti parti:

▲
Quantum Circuit
BLOCK 1
Input Gates
(State Prep)
↓
BLOCK 2
CNOT Logic (XOR function)
(qn-2 • q0)
↓
BLOCK 3
Cascaded SWAP
(Shift Register)
↓
MEASURE
M0 ... Mn-1
▼
Python Controller
Classical Processing
Calculate Next State & Update state = read_measured_bits()
qcircuit = rebuild_input(state)
restart(qcircuit)

Il circuito quantistico è diviso in 3 parti: il blocco 1 è l'insieme delle porte quantistiche che realizzano l'input sulla base delle misurazioni d'uscita (usando porte I se il valore è 0 e porte NOT se è 1); il blocco 2 impiega un CNOT con una funzione tipica della porta XOR coinvolgendo il bit q0 iniziale e il penultimo bit qn-2 (in un registro q0,q1,...qn-1); il blocco 3 realizza uno shift register (come visto nei paragrafi precedenti) mediante delle porte SWAP; il blocco di misura collassa gli stati quantistici in valori reali deterministici e li passa a un elaboratore classico in cui del codice python provvede a ricostruire, mediante formalismo CirQ, un nuovo circuito quantistico per ogni passaggio del loop modificando opportunamente le porte del blocco 1.

Di seguito, a titolo di esempio, il PQRNG a 8 qbit direttamente dal software CirQ realizzato, con un input impostato a 01101011 come seed (si può verificare che il primo strato di porte I e NOT realizza la sequenza di bit indicata):


4.2 LFSR

Il circuito quantistico PQRNG realizzato non è di principio niente di particolarmente sofisticato e nemmeno di innovativo; infatti, come indicato in Understanding Cryptography (Springer 2024 - Second Edition), esso implementa un LFSR (Linear Feedback Shift Register), un sistema di generazione di sequenze pseudo-random deterministiche su un seed iniziale che, nelle sue implementazioni con porte logiche classiche, ha trovato diverso impiego in molti sistemi hardware digitali.

Non si tratta neanche di un generatore estremamente valido per la cybersicurezza ma ha il vantaggio di impiegare calcoli facilmente adattabili all'ambito delle macchine quantistiche. Inoltre, l'algoritmo quantistico che lo realizza è semplice e performante e si può estendere a n qbit con facilità e ci ha permesso di introdurre l'impiego di diverse porte quantistiche oltre alla CNOT quali I, X, SWAP.


4.3 Elaborazione ibrida e python

Si può evidenziare che il codice python, in questo progetto di PQRNG, ha due funzioni diverse:

(a) implementa il circuito quantistico interagendo con la libreria CirQ per poi provvedere alla simulazione del suo funzionamento (simulazione dell'elaborazione quantistica);

(b) impiega una logica di funzionamento classica per reiterare la costruzione del circuito con porte diverse a seconda dei suoi stessi risultati.

Dato che le istruzioni date a CirQ potrebbero benissimo comandare un computer quantistico reale e la sua elaborazione, si parla in tal senso di elaborazione ibrida. Il concetto di elaborazione ibrida sta crescendo costantemente soprattutto nell'ambito della combinazione delle attività tra computer quantistici e supercomputer classici. L'idea è quella di far intervenire i primi solo dove necessario per cambiare l'efficacia delle elaborazioni lasciando, laddove non ci siano particolari vantaggi, ai supercomputer classici di operare.


5. Conclusioni e sviluppi futuri: verso il QPP

Al di là della sua valenza didattica come esercizio di programmazione di un'architettura ibrida (Classica/Quantistica) mediante il framework CirQ, questo lavoro sul PQRNG riveste un ruolo fondamentale per uno dei miei prossimi progetti.

Il generatore pseudo-casuale qui analizzato è, infatti, prodromico alla realizzazione di un sistema crittografico più complesso. In un'altra pagina di questo sito web, questo modulo PQRNG verrà integrato come sorgente di entropia deterministica all'interno di un Criptatore Quantistico basato sul protocollo Quantum Permutation Pad (QPP).

L'obiettivo sarà quello di unire la generazione del keystream (realizzata dal PQRNG) con l'algebra delle matrici di permutazione quantistica, costruendo un algoritmo di cifratura che sfrutti le proprietà degli operatori quantistici per offuscare l'informazione, ponendo le basi per implementazioni di sicurezza Quantum-Native.