Partage via


Comment utiliser des Q# projets

Avec Azure Quantum Development Kit, vous pouvez définir des Q# projets, qui sont des structures de dossiers avec plusieurs Q# fichiers pouvant accéder aux opérations et fonctions des autres. Les projets sont utiles pour organiser logiquement votre code source. Vous pouvez également utiliser des projets en tant que dépendances externes ou bibliothèques personnalisées accessibles à partir de sources externes.

Un Q# projet contient un Q# fichier manifeste nommé qsharp.json et un ou plusieurs fichiers *.qs dans une structure de dossiers spécifiée. Lorsqu’un utilisateur ouvre un fichier *.qs dans VS Code ou définit le project_root fichier Jupyter Notebook ou Python, le compilateur recherche la hiérarchie de dossiers environnante pour le fichier manifeste et détermine l’étendue du projet. Si aucun fichier manifeste n’est trouvé, le compilateur fonctionne en mode fichier unique. Un Q# projet peut être créé manuellement ou directement dans VS Code.

Un projet externe Q# est un projet standard Q# qui réside dans un autre répertoire ou sur un dépôt GitHub public et utilise export des instructions pour définir les fonctions et opérations accessibles par des programmes externes. Les programmes définissent le projet externe comme une dépendance dans leur fichier manifeste et utilisent import des instructions pour accéder aux éléments (opérations, fonctions, structs et espaces de noms) dans le projet externe. Pour plus d’informations, consultez Utilisation de projets en tant que dépendances externes.

Prérequis

Pour exécuter des programmes Python, vous aurez également besoin des éléments suivants :

  • Un environnement Python avec Python et Pip installés.
  • Azure Quantum qsharp et azure-quantum packages.

Définir un Q# projet

Un Q# projet est défini par la présence d’un fichier manifeste, nommé qsharp.json et d’un dossier src (qui contient les Q# fichiers sources), dont les deux doivent se trouver dans le dossier racine du projet. Pour Q# les programmes et les projets externes, le Q# compilateur détecte automatiquement le dossier du projet. Pour les programmes Python et les notebooks Jupyter, vous devez spécifier le dossier du Q# projet avec un qsharp.init appel. Toutefois, la structure de dossiers d’un Q# projet reste la même pour tous les types de programmes.

Image montrant la hiérarchie de dossiers d’un Q# projet.

Définition du dossier de projet (Q# programmes)

Lorsqu’un fichier *.qs est ouvert dans VS Code, le Q# compilateur effectue une recherche vers le haut dans la structure de dossiers d’un fichier manifeste. S’il trouve un fichier manifeste, le compilateur inclut ensuite tous les Q# fichiers dans le répertoire /src ou l’un de ses sous-répertoires. Les éléments de chaque fichier sont mis à la disposition de tous les autres fichiers du projet.

Par exemple, étant donné cette structure de dossiers :

  • Teleportation_project
    • qsharp.json
    • src
      • Main.qs
      • TeleportOperations
        • TeleportLib.qs
        • PrepareState
          • PrepareStateLib.qs

lorsque vous ouvrez le fichier /src/TeleportOperation/PrepareState/PrepareStateLib.qs, le Q# compilateur :

  1. Vérifie /src/TeleportOperation/PrepareState/ pour qsharp.json.
  2. Vérifie /src/TeleportOperation pour qsharp.json.
  3. Vérifie /src pour qsharp.json.
  4. Recherche / qsharp.json.
  5. Établit / comme répertoire racine du projet et inclut tous les fichiers *.qs sous la racine du projet, conformément aux paramètres du fichier manifeste.

Créer un fichier manifeste

Un fichier manifeste est un fichier de .json simple nommé qsharp.json qui peut éventuellement inclure des champs auteur, licence et lints . Le fichier manifeste minimum viable est la chaîne {}. Lorsque vous créez un Q# projet dans VS Code, un fichier manifeste minimal est créé pour vous.

{}

Exemples de fichiers manifestes

Voici quelques exemples de la façon dont les fichiers manifeste peuvent définir l’étendue de votre Q# projet.

  • Dans cet exemple, l’auteur est le seul champ spécifié, et par conséquent tous les fichiers *.qs de ce répertoire et tous ses sous-répertoires sont inclus dans le Q# projet.

    {
        "author":"Microsoft",
        "license": "MIT"
    }
    
  • Dans un Q# projet, vous pouvez également utiliser le fichier manifeste pour affiner les paramètres vs Code Q# Linter. Par défaut, les trois règles Linter sont les suivantes :

    • needlessParens: default = allow
    • divisionByZero: default = warn
    • redundantSemicolons: default = warn

    À l’aide du fichier manifeste, vous pouvez définir chaque règle sur allow, warnou error, par exemple

    {
        "author":"Microsoft",
        "lints": [
            {
              "lint": "needlessParens",
              "level": "allow"
            },
            {
              "lint": "redundantSemicolons",
              "level": "warn"
            },
            {
              "lint": "divisionByZero",
              "level": "error"
            }
          ]
    }
    
  • Vous pouvez également utiliser le fichier manifeste pour définir un projet externe Q# en tant que dépendance et accéder à distance aux opérations et fonctions dans ce projet externe. Pour plus d’informations, consultez Utilisation de projets en tant que dépendances externes.

Q# exigences et propriétés du projet

Les exigences et configurations suivantes s’appliquent à tous les Q# projets.

  • Tous les fichiers *.qs que vous souhaitez inclure dans le projet doivent se trouver sous un dossier nommé src, qui doit se trouver sous le dossier racine du Q# projet. Lorsque vous créez un Q# projet dans VS Code, le /src dossier est créé automatiquement.

  • Le fichier manifeste doit être au même niveau que le dossier src . Lorsque vous créez un Q# projet dans VS Code, un fichier minimal est créé automatiquement.

  • Les opérations et les fonctions à partir de fichiers sources dans le projet sont accessibles par d’autres fichiers du projet à l’aide import d’instructions

    import MyMathLib.*;  //imports all the callables in the MyMathLib namespace
    ...
        Multiply(x,y);
    

    ou en les référençant individuellement avec l’espace de noms

    MyMathLib.Multiply(x,y);  
    

Pour Q# les projets uniquement

  • Un seul fichier *.qs dans un Q# projet peut avoir un point d’entrée défini, défini par une seule Main() opération.
  • Le fichier *.qs avec la définition du point d’entrée peut se trouver à n’importe quel niveau sous le fichier manifeste.
  • Toute opération ou fonction mise en cache à partir d’un fichier *.qs n’importe où dans le Q# projet s’affiche en texte prédictif dans VS Code.
  • Si l’espace de noms d’une opération ou d’une fonction sélectionnée n’a pas encore été explicitement ajouté, VS Code ajoute automatiquement l’instruction nécessaire import .

Étapes de création d’un Q# projet

Ces étapes s’appliquent à tous les Q# projets.

  1. Dans l’Explorateur de fichiers VS Code, cliquez avec le bouton droit sur le dossier racine du Q# projet et sélectionnez Créer Q# un projet, ou ouvrez le dossier et sélectionnez Afficher > la palette >Q#de commandes : Créer un Q# projet....

  2. VS Code crée un fichier manifeste minimal dans le dossier et ajoute un /src dossier avec un Main.qs fichier de modèle.

  3. Modifiez le fichier manifeste si nécessaire. Consultez les exemples de fichier manifeste.

  4. Ajoutez et organisez vos Q# fichiers sources sous le /src dossier.

  5. Si vous accédez au Q# projet à partir d’un programme Python ou d’un jupyter Notebook, définissez le chemin du dossier racine à l’aide qsharp.initde . Cet exemple suppose que votre programme se trouve dans le dossier /src du Q# projet :

    qsharp.init(project_root = '../Teleportation_project')
    
  6. Si vous utilisez uniquement Q# des fichiers dans VS Code, lorsque vous ouvrez un fichier, le compilateur recherche un Q# fichier manifeste, détermine le dossier racine du projet, puis analyse le sous-dossier pour les fichiers *.qs.

Remarque

Vous pouvez également créer manuellement le fichier manifeste et le dossier à l’étape /src 2.

Exemple de projet

Ce programme de téléportation quantique est un exemple de Q# projet basé sur la structure de dossiers unique indiquée précédemment et s’exécute sur le simulateur local dans VS Code. Pour exécuter le programme sur du matériel Azure Quantum ou des simulateurs tiers, consultez Prise en main des Q# programmes et VSCode pour connaître les étapes à suivre pour compiler votre programme et vous connecter à votre espace de travail Azure.

L’exemple utilise cette structure de répertoires :

  • Teleportation_project
    • qsharp.json
    • src
      • Main.qs
      • TeleportOperations
        • TeleportLib.qs
        • PrepareState
          • PrepareStateLib.qs

Le fichier manifeste contient les champs d’auteur et de licence :

{
    "author":"Microsoft",
    "license":"MIT"
}

Q# fichiers sources

Le fichier principal, Main.qs, contient le point d’entrée et fait référence à l’espace TeleportOperations.TeleportLib de noms à partir de TeleportLib.qs.


    import TeleportOperations.TeleportLib.Teleport;   // references the Teleport operation from TeleportLib.qs

    operation Main() : Unit {
        use msg = Qubit();
        use target = Qubit();

        H(msg);
        Teleport(msg, target);    // calls the Teleport() operation from TeleportLib.qs
        H(target);

        if M(target) == Zero {
            Message("Teleported successfully!");
        
        Reset(msg);
        Reset(target);
        }
    }

TeleportLib.qs définit l’opération Teleport() et appelle l’opération PrepareBellPair() à partir de PrepareStateLib.qs.


    import TeleportOperations.PrepareState.PrepareStateLib.*;     // references the namespace in PrepareStateLib.qs
 
    operation Teleport(msg : Qubit, target : Qubit) : Unit {
        use here = Qubit();

        PrepareBellPair(here, target);      // calls the PrepareBellPair() operation from PrepareStateLib.qs
        Adjoint PrepareBellPair(msg, here);

        if M(msg) == One { Z(target); }
        if M(here) == One { X(target); }

        Reset(here);
    }

Le fichier PrepareStateLib.qs contient une opération réutilisable standard pour créer une paire Bell.

    
    operation PrepareBellPair(left : Qubit, right : Qubit) : Unit is Adj + Ctl {
        H(left);
        CNOT(left, right);
    }

Exécution des programmes

Sélectionnez l’onglet de l’environnement dans lequel vous exécutez votre programme.

Pour exécuter ce programme, ouvrez le fichier Main.qs dans VS Code, puis sélectionnez Exécuter.

Configuration de Q# projets en tant que dépendances externes

Un Q# projet peut également être configuré en tant que dépendance externe pour d’autres projets, agissant comme une bibliothèque, où les fonctions et les opérations du projet externe Q# sont mises à la disposition de plusieurs Q# projets. Une dépendance externe peut résider sur un partage de lecteur ou publié dans un dépôt GitHub public.

Pour utiliser un Q# projet comme dépendance externe, vous devez :

  • Ajoutez le projet externe en tant que dépendance dans le fichier manifeste du projet appelant.
  • Si le projet externe est publié sur GitHub, ajoutez la propriété « fichiers » au fichier manifeste du projet externe.
  • Ajoutez des export instructions au projet externe.
  • Ajoutez des import instructions au projet appelant.

Configuration des fichiers manifestes

Les projets externes Q# peuvent résider sur un partage de lecteur local ou réseau, ou publiés dans un dépôt GitHub public.

Fichier manifeste du projet appelant

Pour ajouter une dépendance à un projet externe sur un partage de lecteurs, définissez la dépendance dans le fichier manifeste du projet appelant.

{
    "author": "Microsoft",
    "license": "MIT",
    "dependencies": {
        "MyDependency": {
            "path": "/path/to/project/folder/on/disk"
        }
    }
}

où « MyDependency » est une chaîne définie par l’utilisateur qui identifie l’espace de noms lors de l’appel d’une opération. Par exemple, si vous créez une dépendance nommée « MyMathFunctions », vous appelez une fonction à partir de cette dépendance avec MyMathFunctions.MyFunction().

Pour ajouter une dépendance à un projet publié dans un dépôt GitHub public

{
    "author": "Microsoft",
    "dependencies": {
        "MyDependency": {
            "github": {
                "owner": "GitHubUser",
                "repo": "GitHubRepoName",
                "ref": "CommitHash",
                "path": "/path/to/dependency"
            }
        }
}
  • Pour les dépendances GitHub, « ref » fait référence à une réfspec GitHub. Microsoft recommande d’utiliser toujours un hachage de validation. Vous pouvez donc vous appuyer sur une version spécifique de votre dépendance.

Fichier manifeste du projet externe

Si votre projet externe Q# est publié dans un dépôt GitHub public, vous devez ajouter la propriété fichiers au fichier manifeste du projet externe, y compris tous les fichiers utilisés dans le projet.

{
    "author": "Microsoft",
    "license": "MIT",
    "files": [ "src/MyMathFunctions.qs", "src/Strings/MyStringFunctions.qs" ]
}

La propriété « files » est facultative pour un projet externe importé via "path" (c’est-à-dire une importation basée sur un chemin de fichier local). Il n’est nécessaire que pour les projets publiés sur GitHub.

Utilisation de l’instruction export

Pour rendre les fonctions et les opérations dans un projet externe accessibles aux projets appelants, vous utilisez l’instruction export . Vous pouvez exporter l’un ou l’ensemble des callables dans le fichier. La syntaxe des caractères génériques n’est pas prise en charge, vous devez spécifier chaque appelant à exporter.

operation Operation_A() : Unit {
...
}
operation Operation_B() : Unit  {
...
}

// makes just Operation_A available to calling programs
export Operation_A;           

// makes Operation_A and Operation_B available to calling programs         
export Operation_A, Operation_B, etc.; 

// makes Operation_A available as 'OpA'
export Operation_A as OpA;             

Utilisation de l’instruction import

À partir du programme appelant, vous utilisez import des instructions pour rendre les éléments d’une dépendance externe disponible. import les instructions utilisent l’espace de noms défini pour la dépendance dans le fichier manifeste. Par exemple, pour cette dépendance

{
    "author": "Microsoft",
    "license": "MIT",
    "dependencies": {
        "MyMathFunctions": {
            "path": "/path/to/project/folder/on/disk"
        }
    }
}

vous importez des appelants en tant que

import MyMathFunctions.MyFunction;  // imports "MyFunction()" from the namespace
...

L’instruction import prend également en charge la syntaxe et les alias de caractères génériques

// imports all items from the "MyMathFunctions" namespace
import MyMathFunctions.*;        

// imports the namespace as "Math", all items are accessible via "Math.<callable>"
import MyMathFunctions as Math;   

// imports a single item, available in the local scope as "Add"
import MyMathFunctions.MyFunction as Add;        

// imports can be combined on one line
import MyMathFunctions.MyFunction, MyMathFunctions.AnotherFunction as Multiply; 

Remarque

L’instruction actuellement utilisée open dans Q#, qui est utilisée pour référencer des bibliothèques et des espaces de noms, est toujours prise en charge, mais sera déconseillée finalement. En attendant, vous pouvez éventuellement mettre à jour vos fichiers actuels pour utiliser l’instruction import . Par exemple, open Microsoft.Quantum.Diagnostics; peut être remplacé par import Microsoft.Quantum.Diagnostics.*;.

Exemple de projet externe

Pour cet exemple, vous allez utiliser le même programme de téléportation que l’exemple précédent, mais séparer le programme appelant et les appelants dans différents projets.

  1. Créez deux dossiers sur votre lecteur local, par exemple « Project_A » et « Project_B ».

  2. Créez un Q# projet dans chaque dossier en suivant les étapes de création d’un Q# projet.

  3. Dans Project_A, le programme appelant, copiez le code suivant dans le fichier manifeste, en modifiant le chemin d’accès si nécessaire pour Project_B

    {
      "author": "Microsoft",
      "license": "MIT",
      "dependencies": {
        "MyTeleportLib": {
          "path": "/Project_B" 
          }
        }
      }    
    
  4. Dans Project_A, copiez le code suivant dans Main.qs

    import MyTeleportLib.Teleport;   // imports the Teleport operation from the MyTeleportLib namespace defined in the manifest file
    
    operation Main() : Unit {
        use msg = Qubit();
        use target = Qubit();
    
        H(msg);
        Teleport(msg, target);    // calls the Teleport() operation from the MyTeleportLib namespace
        H(target);
    
        if M(target) == Zero {
            Message("Teleported successfully!");
    
        Reset(msg);
        Reset(target);
        }
    }   
    
  5. Dans Project_B, copiez le code suivant dans Main.qs

    
        operation Teleport(msg : Qubit, target : Qubit) : Unit {
            use here = Qubit();
    
            PrepareBellPair(here, target); 
            Adjoint PrepareBellPair(msg, here);
    
            if M(msg) == One { Z(target); }
            if M(here) == One { X(target); }
    
            Reset(here);
        }
    
        operation PrepareBellPair(left : Qubit, right : Qubit) : Unit is Adj + Ctl {
            H(left);
            CNOT(left, right);
        }
    
        export Teleport;       //  makes the Teleport operation available to external programs
    

    Remarque

    Notez que l’opération PrepareBellPair n’a pas besoin d’être exportée, car elle n’est pas appelée directement à partir de votre programme dans Project_A. Étant donné qu’elle se trouve dans l’étendue locale de Project_B, elle est déjà accessible par l’opération Teleport .

  6. Pour exécuter le programme, ouvrez /Project_A/Main.qs dans VS Code, puis sélectionnez Exécuter.

Projets et espaces de noms implicites

Dans les Q# projets, si un espace de noms n’est pas spécifié dans un programme *.qs, le compilateur utilise le nom de fichier comme espace de noms. Référencer un appelant à partir d’une dépendance externe utilise ensuite la syntaxe <dependencyName>.<espace de noms>.<pouvant être> appelé. Toutefois, si le fichier est nommé « Main.qs », le compilateur part du principe que l’espace de noms et la syntaxe appelante est <dependencyName>.<>pouvant être appelé, comme dans l’exemple précédent, import MyTeleportLib.Teleport.

Étant donné qu’il n’est pas rare d’avoir plusieurs fichiers projet, vous devez tenir compte de la syntaxe correcte lors du référencement des appelants. Par exemple, dans un projet avec la structure de fichiers suivante

  • src/
    • Main.qs
    • MathFunctions.qs

les appels à la dépendance externe seraient

import MyTeleportLib.MyFunction;        // "Main" namespace is implied

import MyTeleportLib.MathFunctions.MyFunction;   // "Math" namespace must be explicit 

Pour plus d’informations sur le comportement de l’espace de noms, consultez Espaces de noms utilisateur.