Struttura di un Q# programma

Questo articolo illustra i componenti generali che costituiscono un Q# programma. Si noti che Q# i programmi scritti in Jupyter Notebooks non usano alcuni di questi componenti. Queste differenze sono descritte in ogni sezione.

Si consideri il programma Q# seguente:

namespace Superposition {

    @EntryPoint()
    operation MeasureOneQubit() : Result {
        // Allocate a qubit, by default it is in zero state      
        use q = Qubit();  
        // We apply a Hadamard operation H to the state
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Now we measure the qubit in Z-basis.
        let result = M(q);
        // We reset the qubit before releasing it.
        Reset(q);
        // Finally, we return the result of the measurement.
        return result;
    }
}

Leggendo solo i commenti (//), è possibile indicare che questo programma alloca un qubit, applica un'operazione per inserirlo in sovrapposizione, misura lo stato del qubit, quindi lo reimposta e restituisce il risultato.

Per eseguire questo programma in Visual Studio Code, vedere Introduzione ai Q# programmi e a VS Code.

Spazi dei nomi utente

Q# i programmi iniziano in genere con uno spazio dei nomi denominato dall'utente, ad esempio

namespace Superposition {
    // Your code goes here.
}

Gli spazi dei nomi consentono di organizzare le funzionalità correlate. Gli spazi dei nomi sono denominati dall'utente e possono essere presenti solo un namespace file qsharp (*.qs).

La Q# libreria standard include spazi dei nomi predefiniti che contengono funzioni e operazioni che è possibile usare nei programmi quantistici. Per altre informazioni, vedere Spazi dei nomi predefiniti.

I notebook di Jupyter non usano spazi dei nomi utente.

EntryPoint()

L'attributo @EntryPoint() indica al Q# compilatore dove iniziare l'esecuzione del programma. Nei programmi con più definizioni di funzione e operazione, è possibile posizionare prima @EntryPoint() che una qualsiasi delle funzioni o delle operazioni e del flusso del programma inizi da lì e continui in sequenza.

    ...
    @EntryPoint()
    operation MeasureOneQubit() : Result {
        ...

I notebook di Jupyter non usano punti di ingresso.

Comando %%qsharp

Per impostazione predefinita, Q# i programmi in Jupyter Notebook usano il kernel Python ipykernel . Per aggiungere Q# codice a una cella del notebook, è necessario usare il %%qsharp comando , che è abilitato con il qsharp pacchetto Python. Ad esempio, il codice di esempio precedente in un Jupyter Notebook è simile al seguente:

import qsharp
%%qsharp

    operation MeasureOneQubit() : Result {
        // Allocate a qubit, by default it is in zero state      
        use q = Qubit();  
        // We apply a Hadamard operation H to the state
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Now we measure the qubit in Z-basis.
        let result = M(q);
        // We reset the qubit before releasing it.
        Reset(q);
        // Display the result
        Message($"Result is {result}");
        // Finally, we return the result of the measurement.
        return result;
    
    }
    MeasureOneQubit();

Si noti l'assenza di uno spazio dei nomi utente o di un @EntryPoint()oggetto , che non sono necessari per i notebook di Jupyter. Anziché un punto di ingresso, l'operazione viene chiamata direttamente nell'ultima riga. Si noti inoltre che un'istruzione Message è stata aggiunta al codice Jupyter Notebook per visualizzare il risultato. Quando si esegue il programma precedente Q# in VS Code, il simulatore predefinito visualizza il risultato per impostazione predefinita.

Quando si usa il %%qsharp comando :

  • È necessario prima eseguire import qsharp per abilitare il %%qsharp comando.
  • Il %%qsharp comando ha come ambito l'intera cella in cui viene visualizzata.
  • Il Q# codice che segue il comando deve rispettare la sintassi di codifica standard Q# . Ad esempio, si denotano i commenti usando // anziché all'interno %%qsharp di # celle e le righe di codice devono terminare con un punto ;e virgola.
  • Il %%qsharp comando non può essere preceduto da o seguito da un'istruzione Python all'interno della relativa cella.

Per un esempio di utilizzo di un programma Jupyter Notebook, vedere Introduzione ai Q# programmi e a VS Code.

Tipi

Q# fornisce molti tipi predefiniti comuni alla maggior parte dei linguaggi, tra cui Int, Double, Boole String, insieme ai tipi specifici del calcolo quantistico. Ad esempio, il Result tipo rappresenta il risultato di qualsiasi misura qubit e può avere uno dei due valori definiti possibili: One e Zero. Nel programma di esempio l'operazione MeasureOneQubit() prevede un tipo restituito di Result e l'operazione M misura il qubit e restituisce .Result

...
// operation definition expecting a return type of Result
operation MeasureOneQubit() : Result {
    ...
    // Now we measure the qubit in Z-basis, returning a Result type
    let result = M(q);
    ...
}

Q# include anche tipi che definiscono intervalli, matrici e tuple. Si possono persino definire tipi personalizzati.

Allocazione di qubit

In Q# i qubit vengono allocati tramite la parola chiave use.

L'esempio definisce un singolo qubit:

// Allocate a qubit.
use q = Qubit();
...

ma è anche possibile allocare più qubit e accedervi tramite il relativo indice:

...
use qubits = Qubit[2];
X(qubits[1]);
H(qubits[0]);
...

Per impostazione predefinita, ogni qubit allocato con la parola chiave use inizia con lo stato zero. Ogni qubit deve essere reimpostato lo stato zero prima che venga rilasciato alla fine del programma. Se non si reimposta un qubit, viene generato un errore di runtime.

// Reset a qubit.
Reset(q);
...

Operazioni quantistice

Una volta allocato, un qubit può essere passato a operazioni e funzioni, definite anche elementi chiamabili. Le operazioni sono i blocchi predefiniti di base di un programma Q#. Un'operazione Q# è una subroutine quantistica. Ovvero, una routine chiamabile che contiene operazioni quantistiche che modificano lo stato del registro qubit.

Per definire un'operazione Q#, è necessario specificare un nome per l'operazione insieme ai relativi input e output. In questo esempio, la singola operazione è essenzialmente l'intero programma. Non accetta parametri e prevede un tipo restituito di Result:

operation MeasureOneQubit() : Result {
    ...
}

Ecco un esempio di base che non accetta parametri e non prevede alcun valore restituito. Il Unit valore equivale a NULL in altre lingue.

operation SayHelloQ() : Unit {
    Message("Hello quantum world!");
}

La Q# libreria standard fornisce anche operazioni che è possibile usare nei programmi, ad esempio Hadamard o l'operazione H usata nel programma di esempio. Dato un qubit in Z, l'operazione H inserisce il qubit in una sovrapposizione uniforme . Una volta in sovrapposizione, il qubit ha una probabilità del 50% di essere misurata come zero o uno.

Misurazione dei qubit

Esistono molti tipi di misurazioni quantistiche, ma Q# si concentra sulle misurazioni proiettative su singoli qubit, note anche come misurazioni Pauli. In base a una determinata misura (ad esempio, la base di calcolo $\ket{0},\ket{1}$) lo stato del qubit viene proiettato su qualsiasi stato di base misurato, di conseguenza distruggendo qualsiasi sovrapposizione tra i due.

Il programma di esempio usa l'operazione M , che esegue una misurazione di un singolo qubit nella base Pauli Z e restituisce un Result tipo.

Spazi dei nomi predefiniti

La libreria standard Q# usa spazi dei nomi predefiniti che contengono funzioni e operazioni che è possibile usare nei programmi quantistici. Ad esempio, lo spazio dei nomi Microsoft.Quantum.Intrinsic contiene funzioni e operazioni di uso comune, Mad esempio , per misurare i risultati e Message, per visualizzare i messaggi utente in qualsiasi punto del programma.

È possibile chiamare una funzione o un'operazione specificando lo spazio dei nomi completo oppure usare un'istruzione open per rendere disponibili tutte le funzioni e le operazioni per tale spazio dei nomi e per semplificare la lettura del codice. Questi due esempi chiamano la stessa operazione:

 Microsoft.Quantum.Intrinsic.Message("Hello quantum world!");
open Microsoft.Quantum.Intrinsic;
Message("Hello quantum world!");

Si noti che nel programma di esempio non open sono presenti istruzioni o chiamate con spazi dei nomi completi. Ciò è dovuto al fatto che l'ambiente Q# di sviluppo carica automaticamente due spazi dei nomi per impostazione predefinita e Microsoft.Quantum.CoreMicrosoft.Quantum.Intrinsic , che contengono funzioni e operazioni di uso comune.

È possibile sfruttare lo Microsoft.Quantum.Measurement spazio dei nomi e usare l'operazione MResetZ per ottimizzare il codice nel programma di esempio. MResetZ combina le operazioni di misurazione e reimpostazione in un unico passaggio, come nell'esempio seguente:

namespace Superposition {

    // open the namespace for the MResetZ operation
    open Microsoft.Quantum.Measurement;

    @EntryPoint()
    operation MeasureOneQubit() : Result {
        // Allocate a qubit, by default it is in zero state      
        use q = Qubit();  
        // We apply a Hadamard operation H to the state
        // It now has a 50% chance of being measured 0 or 1  
        H(q);   
        // Measure and reset the qubit, and return the result value   
        return MResetZ(q);
    }
    
}