Structure d’un Q# programme

Cet article explore les composants généraux qui composent un Q# programme. Notez que Q# les programmes écrits dans Jupyter Notebooks n’utilisent pas certains de ces composants. Ces différences sont décrites dans chaque section.

Prenons le programme en Q# suivant :

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

En lisant simplement les commentaires (//), vous pouvez savoir que ce programme alloue un qubit, applique une opération pour le mettre en superposition, mesure l’état du qubit, puis le réinitialise et retourne le résultat.

Pour exécuter ce programme dans Visual Studio Code, consultez Bien démarrer avec Q# les programmes et VS Code.

Espaces de noms utilisateur

Q# les programmes commencent généralement par un espace de noms nommé par l’utilisateur, tel que

namespace Superposition {
    // Your code goes here.
}

Les espaces de noms vous aident à organiser les fonctionnalités associées. Les espaces de noms sont nommés par l’utilisateur et il ne peut y en avoir qu’un namespace par fichier qsharp (*.qs).

La Q# bibliothèque standard dispose d’espaces de noms prédéfinis qui contiennent des fonctions et des opérations que vous pouvez utiliser dans les programmes quantiques. Pour plus d’informations, consultez Espaces de noms intégrés.

Les notebooks Jupyter n’utilisent pas d’espaces de noms utilisateur.

EntryPoint()

L’attribut @EntryPoint() indique au Q# compilateur où commencer l’exécution du programme. Dans les programmes avec plusieurs définitions de fonction et d’opération, le @EntryPoint() peut être placé avant l’une des fonctions ou opérations et le flux de programme commence à partir de là et se poursuit de manière séquentielle.

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

Les notebooks Jupyter n’utilisent pas de points d’entrée.

Commande %%qsharp

Par défaut, Q# les programmes dans Jupyter Notebooks utilisent le noyau Python ipykernel . Pour ajouter Q# du code à une cellule de notebook, vous devez utiliser la %%qsharp commande, qui est activée avec le qsharp package Python. Par exemple, l’exemple de code précédent dans un Jupyter Notebook ressemble à ceci :

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

Notez l’absence d’un espace de noms utilisateur ou d’un @EntryPoint(), qui ne sont pas nécessaires pour les notebooks Jupyter. Au lieu d’un point d’entrée, l’opération est appelée directement dans la dernière ligne. Notez également qu’une Message instruction a été ajoutée au code Jupyter Notebook pour afficher le résultat. Lorsque vous exécutez le programme précédent Q# dans VS Code, le simulateur intégré affiche le résultat par défaut.

Lors de l’utilisation de la %%qsharp commande :

  • Vous devez d’abord exécuter import qsharp pour activer la commande %%qsharp.
  • La %%qsharp commande est limitée à la cellule entière dans laquelle elle apparaît. Notez qu’il change le type de cellule de notebook de Python en Q#.
  • Le code Q# qui suit la commande doit respecter la syntaxe de codage standard de Q#. Par exemple, vous désignez les commentaires en utilisant // au lieu de dans %%qsharp des cellules, et les lignes de # code doivent se terminer par un point-virgule ;.
  • La commande %%qsharp ne peut pas être précédée ou suivie d’une instruction Python dans sa cellule.

Pour obtenir un exemple d’utilisation d’un programme Jupyter Notebook, consultez Prise en main des Q# programmes et de VS Code.

Types

Q#fournit de nombreux types intégrés communs à la plupart des langages, notamment Int, , BoolDoubleet , ainsi Stringque des types spécifiques à l’informatique quantique. Par exemple, le Result type représente le résultat d’une mesure de qubit et peut avoir l’une des deux valeurs définies possibles : One et Zero. Dans l’exemple de programme, l’opération MeasureOneQubit() attend un type de retour de Result et l’opération M mesure le qubit et retourne le 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# fournit également des types qui définissent des plages, des tableaux et des tuples. Vous pouvez même définir vos propres types personnalisés.

Allocation de qubits

Dans Q#, les qubits sont alloués par le biais du mot clé use.

Notre exemple définit un qubit unique :

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

mais vous pouvez également allouer plusieurs qubits et accéder à chacun d’eux via son index :

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

Par défaut, chaque qubit que vous allouez avec le mot clé use commence à l’état zéro. Chaque qubit doit être réinitialisé à l’état zéro avant d’être libéré à la fin du programme. L’échec de la réinitialisation d’un qubit déclenche une erreur d’exécution.

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

Opérations quantiques

Une fois alloué, un qubit peut être transmis à des opérations et à des fonctions, qu’on appelle callables (appelables). Les opérations sont à la base des programmes en Q#. Une opération Q# est une sous-routine quantique. Autrement dit, il s’agit d’une routine pouvant être appelée qui contient des opérations quantiques permettant de modifier l’état du registre de qubits.

Pour définir une opération Q#, vous devez spécifier un nom pour celle-ci, ainsi que ses entrées et sa sortie. Dans notre exemple, l’opération unique est essentiellement le programme entier. Il ne prend aucun paramètre et attend un type de retour de Result:

operation MeasureOneQubit() : Result {
    ...
}

Voici un exemple de base qui ne prend aucun paramètre et n’attend aucune valeur de retour. La Unit valeur est équivalente à NULL dans d’autres langues.

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

La Q# bibliothèque standard fournit également des opérations que vous pouvez utiliser dans vos programmes, par exemple Hadamard ou l’opération H utilisée dans l’exemple de programme. Pour un qubit en base Z, l'opération H place le qubit dans une superposition paire. Une fois dans la superposition, le qubit a une probabilité de 50 % d’avoir une valeur de 0 ou de 1 après mesure.

Mesure des qubits

Il existe de nombreux types de mesures quantiques, mais Q# se concentre sur les mesures projectives sur des qubits uniques, également appelés mesures de Pauli. En cas de mesure dans une base donnée (par exemple, la base de calcul $\ket{0},\ket{1}$), l’état du qubit est projeté sur tout état de base qui a été mesuré, détruisant ainsi toute superposition entre les deux.

Notre exemple de programme utilise l’opération M , qui effectue une mesure d’un qubit unique dans la base Z de Pauli et retourne un Result type.

Espaces de noms intégrés

La bibliothèque standard Q# utilise des espaces de noms intégrés qui contiennent des fonctions et des opérations que vous pouvez utiliser dans les programmes quantiques. Par exemple, l’espace de noms Microsoft.Quantum.Intrinsic contient des opérations et des fonctions couramment utilisées telles que M, pour mesurer les résultats et Message, pour afficher les messages utilisateur n’importe où dans le programme.

Vous pouvez appeler une fonction ou une opération en spécifiant l’espace de noms complet, ou utiliser une open instruction pour rendre toutes les fonctions et opérations de cet espace de noms disponibles et pour faciliter la lecture de votre code. Ces deux exemples appellent la même opération :

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

Notez que dans l’exemple de programme, il n’y a pas open d’instructions ou d’appels avec des espaces de noms complets. En effet, l’environnement de Q# développement charge automatiquement deux espaces de noms par défaut - Microsoft.Quantum.Core et Microsoft.Quantum.Intrinsic - qui contiennent des fonctions et des opérations couramment utilisées.

Vous pouvez tirer parti de l’espace Microsoft.Quantum.Measurement de noms et utiliser l’opération MResetZ pour optimiser le code dans l’exemple de programme. MResetZ combine les opérations de mesure et de réinitialisation en une seule étape, comme dans l’exemple suivant :

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