Structuur van een Q# programma

In dit artikel worden de algemene onderdelen besproken waaruit een Q# programma bestaat. Houd er rekening mee dat programma's die Q# zijn geschreven in Jupyter Notebooks sommige van deze onderdelen niet gebruiken. Deze verschillen worden in elke sectie beschreven.

Bekijk het volgende Q# programma:

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;
    }
}

Door alleen de opmerkingen (//) te lezen, kunt u zien dat dit programma een qubit toewijst, een bewerking toepast om deze in superpositie te plaatsen, de status van de qubit meet, deze vervolgens opnieuw instelt en het resultaat retourneert.

Als u dit programma wilt uitvoeren in Visual Studio Code, raadpleegt u Aan de slag met Q# programma's en VS Code.

Gebruikersnaamruimten

Q# programma's beginnen meestal met een door de gebruiker benoemde naamruimte, zoals

namespace Superposition {
    // Your code goes here.
}

Met naamruimten kunt u gerelateerde functionaliteit organiseren. Naamruimten hebben een gebruikersnaam en er kan slechts één namespace per qsharp(*.qs)-bestand zijn.

De Q# standaardbibliotheek bevat vooraf gedefinieerde naamruimten die functies en bewerkingen bevatten die u in kwantumprogramma's kunt gebruiken. Zie Ingebouwde naamruimten voor meer informatie.

Jupyter Notebooks maken geen gebruik van gebruikersnaamruimten.

EntryPoint()

Het @EntryPoint() kenmerk geeft aan waar de Q# compiler moet beginnen met het uitvoeren van het programma. In programma's met meerdere functie- en bewerkingsdefinities kan de @EntryPoint() worden geplaatst voordat een van de functies of bewerkingen en programmastroom van daaruit wordt gestart en sequentieel wordt voortgezet.

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

Jupyter Notebooks maken geen gebruik van toegangspunten.

De opdracht %%qsharp

Programma's in Jupyter Notebooks gebruiken standaard Q# de ipykernel Python-kernel. Als u code wilt toevoegen Q# aan een notebookcel, moet u de %%qsharp opdracht gebruiken, die is ingeschakeld met het qsharp Python-pakket. De vorige voorbeeldcode in een Jupyter Notebook ziet er bijvoorbeeld als volgt uit:

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();

Let op de afwezigheid van een gebruikersnaamruimte of een @EntryPoint(), die niet nodig zijn voor Jupyter Notebooks. In plaats van een toegangspunt wordt de bewerking rechtstreeks in de laatste regel aangeroepen. Houd er ook rekening mee dat er een Message instructie is toegevoegd aan de Jupyter Notebook code om het resultaat weer te geven. Wanneer u het eerdere Q# programma in VS Code uitvoert, wordt het resultaat standaard weergegeven in de ingebouwde simulator.

Wanneer u de %%qsharp opdracht gebruikt:

  • U moet eerst uitvoeren import qsharp om de %%qsharp opdracht in te schakelen.
  • De %%qsharp opdracht is gericht op de hele cel waarin deze wordt weergegeven. Houd er rekening mee dat het celtype van het notebook wordt gewijzigd van Python in Q#.
  • De Q# code die volgt op de opdracht moet voldoen aan de standaardcoderingssyntaxis Q# . U geeft bijvoorbeeld opmerkingen aan met behulp // van in plaats van # binnen %%qsharp cellen en coderegels moeten eindigen op een puntkomma ;.
  • De %%qsharp opdracht kan niet worden voorafgegaan door of gevolgd door een Python-instructie in de cel.

Zie Aan de slag met programma's en VS Code voor een voorbeeld van het werken met Q# een Jupyter Notebook-programma.

Typen

Q# biedt veel ingebouwde typen die gebruikelijk zijn voor de meeste talen, waaronder Int, Double, Boolen , samen Stringmet typen die specifiek zijn voor kwantumcomputing. Het type vertegenwoordigt bijvoorbeeld het Result resultaat van een qubitmeting en kan een van de twee mogelijke gedefinieerde waarden hebben: One en Zero. In het voorbeeldprogramma verwacht de bewerking MeasureOneQubit() een retourtype van Result en meet de M bewerking de qubit en retourneert de 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# biedt ook typen waarmee bereiken, matrices en tuples worden gedefinieerd. U kunt zelfs uw eigen aangepaste typen definiëren.

Qubits toewijzen

In Q#worden qubits toegewezen via het use trefwoord.

In ons voorbeeld wordt één qubit gedefinieerd:

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

Maar u kunt ook meerdere qubits toewijzen en toegang krijgen tot elke qubit via de index:

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

Standaard begint elke qubit die u toewijst met het use trefwoord met de status nul. Elke qubit moet de nulstatus opnieuw worden ingesteld voordat deze aan het einde van het programma wordt vrijgegeven. Als u een qubit niet opnieuw instelt, wordt een runtimefout geactiveerd.

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

Kwantumbewerkingen

Zodra een qubit is toegewezen, kan deze worden doorgegeven aan bewerkingen en functies, ook wel aanroepbare functies genoemd. Bewerkingen zijn de basisbouwstenen van een Q# programma. Een Q# bewerking is een kwantumsubroutine. Dat wil zeggen dat het een aanroepbare routine is die kwantumbewerkingen bevat waarmee de status van het qubit-register wordt gewijzigd.

Als u een Q# bewerking wilt definiëren, geeft u een naam op voor de bewerking, samen met de invoer en uitvoer. In ons voorbeeld is de enkele bewerking in feite het hele programma. Er zijn geen parameters nodig en er wordt een retourtype van verwacht:Result

operation MeasureOneQubit() : Result {
    ...
}

Hier volgt een eenvoudig voorbeeld waarbij geen parameters worden gebruikt en geen retourwaarde wordt verwacht. De Unit waarde is gelijk aan NULL in andere talen.

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

De Q# standaardbibliotheek biedt ook bewerkingen die u in uw programma's kunt gebruiken, bijvoorbeeld de Hadamard of de H bewerking die wordt gebruikt in het voorbeeldprogramma. Op basis van een qubit in Z-basis plaatst de H bewerking de qubit in een gelijkmatige superpositie. Eenmaal in superpositie heeft de qubit een kans van 50% om te worden gemeten als nul of één.

Qubits meten

Er zijn veel soorten kwantummetingen, maar Q# deze zijn gericht op projectieve metingen op enkele qubits, ook wel Pauli-metingen genoemd. Bij metingen in een bepaalde basis (bijvoorbeeld de rekenkundige basis $\ket{0},\ket{1}$) wordt de qubitstatus geprojecteerd op de basistoestand die is gemeten, waardoor elke superpositie tussen de twee wordt vernietigd.

In ons voorbeeldprogramma wordt de M bewerking gebruikt, die een meting van één qubit uitvoert in de Pauli Z-basis en een Result type retourneert.

Ingebouwde naamruimten

De standaardbibliotheek Q# maakt gebruik van ingebouwde naamruimten die functies en bewerkingen bevatten die u in kwantumprogramma's kunt gebruiken. De naamruimte Microsoft.Quantum.Intrinsic bevat bijvoorbeeld veelgebruikte bewerkingen en functies zoals M, om resultaten te meten en Message, om gebruikersberichten overal in het programma weer te geven.

U kunt een functie of bewerking aanroepen door de volledige naamruimte op te geven of een open -instructie gebruiken om alle functies en bewerkingen voor die naamruimte beschikbaar te maken en uw code beter leesbaar te maken. In deze twee voorbeelden wordt dezelfde bewerking aangeroepen:

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

U ziet dat er in het voorbeeldprogramma geen open instructies of aanroepen met volledige naamruimten zijn. Dat komt omdat de Q# ontwikkelomgeving automatisch twee naamruimten laadt , Microsoft.Quantum.Core en Microsoft.Quantum.Intrinsic - die veelgebruikte functies en bewerkingen bevatten.

U kunt profiteren van de Microsoft.Quantum.Measurement naamruimte en de MResetZ bewerking gebruiken om de code in het voorbeeldprogramma te optimaliseren. MResetZ combineert de bewerkingen voor meten en opnieuw instellen in één stap, zoals in het volgende voorbeeld:

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);
    }
    
}