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 nel suo insieme. Al contrario, un programma alloca e rilascia qubit, o memoria quantistica, man mano che va. A questo proposito, Q# modella il computer quantistico come un heap di qubit.

Anziché supportare istruzioni di allocazione e rilascio separate 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 di tale istruzione di blocco. Il blocco di istruzioni può essere definito in modo implicito quando si allocano i qubit per la durata dell'ambito corrente, come descritto in modo più dettagliato nelle sezioni relative alle use istruzioni e borrow . Il tentativo di accedere ai qubit allocati dopo che l'istruzione termina genera un'eccezione di runtime.

Q# ha 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 qubit puliti e dirty . I qubit puliti non sono separati e non vengono usati da un'altra parte del calcolo. I qubit dirty sono qubit il cui stato è sconosciuto e possono anche essere entangled 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, seguiti da un segno di uguale = e una singola tupla o una tupla corrispondente di inizializzatori.

Gli inizializzatori sono disponibili per un singolo qubit, indicato come Qubit(), o per 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]) {
    // ...
}

È garantito che i qubit siano in uno stato |0⟩ al momento dell'allocazione. Vengono rilasciati alla fine dell'ambito e devono essere in stato |0⟩ al rilascio. Questo requisito non viene applicato dal compilatore perché ciò richiede una valutazione simbolica che diventa rapidamente dispendiosa in modo proibitivo. Quando si esegue nei simulatori, è possibile applicare il requisito di runtime. Nei processori quantistici, il requisito non può essere applicato in fase di esecuzione. Un qubit non misurato può essere reimpostato su |0⟩ tramite una trasformazione unitaria. In caso contrario, il comportamento non è corretto.

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

Dichiarazione di 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 le parti di una subroutine, questi 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 nel tempo spaziale.

Un'istruzione borrow segue lo stesso modello descritto in precedenza per l'istruzioneuse, 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 sono in uno stato sconosciuto e non sono più in ambito alla fine del blocco di istruzioni. Il mutuatario 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 non devono essere usati dal programma dal momento in cui il qubit viene associato fino all'ultimo uso di tale qubit. Se non sono disponibili qubit sufficienti per prendere in 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 controlli CNOT multicontrolli che richiedono pochissimi qubit e implementazioni di incrementi. Questo documento sul factoring con qubit fornisce un esempio di algoritmo che usa qubit presi in prestito.