Condividi tramite


Gestione della memoria quantistica

Un programma viene sempre avviato senza qubit, ovvero non è possibile passare valori di tipo Qubit come argomenti del punto di ingresso. Questa restrizione è intenzionale perché lo scopo di Q# è esprimere e ragionare su un programma nella sua interezza. Al contrario, un programma alloca e rilascia qubit, o memoria quantistica, man mano che va. A questo proposito, Q# modella il computer quantistico come heap qubit.

Invece di supportare istruzioni di rilascio separate allocare e per la memoria quantistica, Q# supporta l'allocazione di memoria quantistica sotto forma di istruzioni a blocchi , in cui la memoria è accessibile solo nell'ambito dell'istruzione block. Il blocco di istruzioni può essere definito in modo implicito quando si allocano qubit per la durata dell'ambito corrente, come descritto in modo più dettagliato nelle sezioni relative alle istruzioni use e borrow. Il tentativo di accedere ai qubit allocati dopo che l'istruzione termina genera un'eccezione di runtime.

Q# include due istruzioni, use e borrow, che creano un'istanza di valori qubit, matrici di qubit o qualsiasi combinazione corrispondente. È possibile usare queste istruzioni solo all'interno delle operazioni. Raccolgono i valori qubit di cui è stata creata un'istanza, li associano alle variabili specificate nell'istruzione e quindi eseguono un blocco di istruzioni. Alla fine del blocco, le variabili associate escono dall'ambito e non sono più definite.

Q# distingue tra l'allocazione di pulite e qubit dirty. I qubit puliti vengono scollegati e non vengono usati da un'altra parte del calcolo. I qubit dirty sono qubit il cui stato è sconosciuto e possono anche essere intangibili con altre parti della memoria del processore quantistico.

Istruzione Use

I qubit puliti vengono allocati dall'istruzione use.

  • L'istruzione è costituita dalla parola chiave use seguita da un'associazione e da un blocco di istruzioni facoltativo.
  • Se è presente un blocco di istruzioni, i qubit sono disponibili solo all'interno di tale blocco. In caso contrario, i qubit sono disponibili fino alla fine dell'ambito corrente.
  • L'associazione segue lo stesso modello delle istruzioni let: un singolo simbolo o una tupla di simboli, seguito da un segno di uguale =e da una tupla singola o una tupla corrispondente di inizializzatori .

Gli inizializzatori sono disponibili per un singolo qubit, indicato come Qubit()o una matrice di qubit, Qubit[n], dove n è un'espressione Int. Ad esempio:

use qubit = Qubit();
// ...

use (aux, register) = (Qubit(), Qubit[5]);
// ...

use qubit = Qubit() {
    // ...
}

use (aux, register) = (Qubit(), Qubit[5]) {
    // ...
}

I qubit sono sicuramente in uno stato |0⟩ all'allocazione. Vengono rilasciati alla fine dell'ambito e devono essere in stato |0⟩ al rilascio. Questo requisito non è applicato dal compilatore perché ciò richiederebbe una valutazione simbolica che diventa rapidamente costoso in modo proibitivo. Quando si esegue nei simulatori, il requisito può essere applicato in fase di esecuzione. Nei processori quantistici, il requisito non può essere applicato in fase di esecuzione; Un qubit non misurato può essere reimpostato su |0⟩ tramite trasformazione unitaria. In caso contrario, si verifica un comportamento errato.

L'istruzione use alloca i qubit dall'heap del qubit libero del processore quantistico e li restituisce all'heap non oltre la fine dell'ambito in cui sono associati i qubit.

Estratto in prestito

L'istruzione borrow concede l'accesso ai qubit già allocati ma non attualmente in uso. Questi qubit possono trovarsi in uno stato arbitrario e devono trovarsi di nuovo nello stesso stato quando l'istruzione borrow termina. Alcuni algoritmi quantistici possono usare qubit senza basarsi sul proprio stato esatto e senza richiedere che siano scollegati con il resto del sistema. Ciò significa che richiedono temporaneamente qubit aggiuntivi, ma possono garantire che tali qubit vengano restituiti esattamente allo stato originale, indipendentemente dallo stato in cui si trovava.

Se sono presenti qubit in uso ma non toccati durante parti di una subroutine, tali qubit possono essere presi in prestito per l'uso da parte di tale algoritmo anziché allocare memoria quantistica aggiuntiva. Il prestito anziché l'allocazione può ridurre significativamente i requisiti generali di memoria quantistica di un algoritmo ed è un esempio quantistico di un tipico compromesso tra il tempo e lo spazio.

Un'istruzione borrow segue lo stesso modello descritto in precedenza per l'istruzione use, con gli stessi inizializzatori disponibili. Ad esempio:

borrow qubit = Qubit();
// ...

borrow (aux, register) = (Qubit(), Qubit[5]);
// ...

borrow qubit = Qubit() {
    // ...
}

borrow (aux, register) = (Qubit(), Qubit[5]) {
    // ...
}

I qubit presi in prestito si trovano in uno stato sconosciuto e non rientrano nell'ambito alla fine del blocco di istruzioni. Il prestito si impegna a lasciare i qubit nello stesso stato di quando sono stati presi in prestito; ovvero, il relativo stato all'inizio e la fine del blocco di istruzioni deve essere lo stesso.

L'istruzione borrow recupera i qubit in uso che sono garantiti non essere usati dal programma dal momento in cui il qubit è associato fino all'ultimo uso di tale qubit. Se non sono disponibili qubit sufficienti per il prestito, i qubit vengono allocati da e restituiti all'heap come un'istruzione use.

Nota

Tra i casi d'uso noti di qubit dirty sono implementazioni di porte CNOT multi-controllate che richiedono pochissimi qubit e implementazioni di incrementatori. Questo paper sul factoring con qubit fornisce un esempio di algoritmo che usa qubit presi in prestito.