Skapa och hantera Q# projekt och anpassade bibliotek
I den här artikeln får du lära dig hur du skapar, hanterar och delar Q# projekt. Q# projekt är mappstrukturer med flera Q# filer som kan komma åt varandras åtgärder och funktioner. Projekt är användbara för att logiskt organisera källkoden. Du kan också använda projekt som anpassade bibliotek som kan nås från externa källor.
Förutsättningar
- En Azure Quantum-arbetsyta i din Azure-prenumeration. Information om hur du skapar en arbetsyta finns i Skapa en Azure Quantum-arbetsyta.
- Visual Studio Code med AzureQuantum Development Kit- och Python-tillägget installerat.
- Ett GitHub-konto om du planerar att publicera ditt externa projekt till en offentlig GitHub-lagringsplats.
För att köra Python-program behöver du också:
- En Python-miljö med Python och Pip installerade.
- Azure Quantum
qsharp
ochazure-quantum
paket.
Så Q# här fungerar projekt
Ett Q# projekt innehåller en Q# manifestfil med namnet qsharp.json och en eller flera *.qs-filer i en angiven mappstruktur. När en användare öppnar en *.qs-fil i VS Code, eller anger project_root
i en Jupyter Notebook- eller Python-fil, söker kompilatorn i den omgivande mapphierarkin efter manifestfilen och avgör projektets omfång. Om ingen manifestfil hittas fungerar kompilatorn i ett enda filläge. Du kan skapa ett Q# projekt manuellt eller direkt i VS Code.
Ett externt Q# projekt är ett standardprojekt Q# som finns i en annan katalog eller på en offentlig GitHub-lagringsplats och fungerar som ett anpassat bibliotek. Ett externt projekt använder export
instruktioner för att definiera vilka funktioner och åtgärder som kan nås av externa program. Program definierar det externa projektet som ett beroende i manifestfilen och använder import
instruktioner för att komma åt objekten (åtgärder, funktioner, structs och namnområden) i det externa projektet. Mer information finns i Använda projekt som externa beroenden.
Definiera ett Q# projekt
Ett Q# projekt definieras av förekomsten av en manifestfil med namnet qsharp.json och en src-mapp (som innehåller källfilerna Q# ), som båda måste finnas i projektets rotmapp. För Q# program och externa projekt Q# identifierar kompilatorn projektmappen automatiskt. För Python-program och Jupyter Notebooks måste du ange projektmappen Q# med ett qsharp.init
anrop. Mappstrukturen för ett Q# projekt är dock densamma för alla typer av program.
Definiera projektmappen (Q# program)
När en *.qs-fil öppnas i VS Code Q# söker kompilatorn uppåt i mappstrukturen efter en manifestfil. Om den hittar en manifestfil innehåller kompilatorn sedan alla Q# filer i katalogen /src eller någon av dess underkataloger. Varje fils objekt görs tillgängliga för alla andra filer i projektet.
Till exempel med tanke på den här mappstrukturen:
- Teleportation_project
- qsharp.json
- Src
- Main.qs
- TeleportOperations
- TeleportLib.qs
- PrepareState
- PrepareStateLib.qs
när du öppnar filen /src/TeleportOperation/PrepareState/PrepareStateLib.qs, Q# kompilatorn:
- Kontrollerar /src/TeleportOperation/PrepareState/ för qsharp.json.
- Kontrollerar /src/TeleportOperation för qsharp.json.
- Kontrollerar /src för qsharp.json.
- Söker efter / qsharp.json.
- Etablerar / som rotkatalogen för projektet och innehåller alla *.qs-filer under roten i projektet, enligt manifestfilens inställningar.
Skapa en manifestfil
En manifestfil är en enkel .json fil med namnet qsharp.json som kan innehålla fält för författare, licens och lints . Den minsta livskraftiga manifestfilen är strängen {}
. När du skapar ett Q# projekt i VS Code skapas en minimal manifestfil åt dig.
{}
Exempel på manifestfil
Följande är några exempel på hur manifestfiler kan definiera projektets Q# omfattning.
I det här exemplet är författare det enda angivna fältet, och därför ingår alla *.qs-filer i den här katalogen och alla dess underkataloger i Q# projektet.
{ "author":"Microsoft", "license": "MIT" }
I ett Q# projekt kan du också använda manifestfilen för att finjustera VS Code Q# Linter-inställningarna. Som standard är de tre Linter-reglerna:
needlessParens
: default =allow
divisionByZero
: default =warn
redundantSemicolons
: default =warn
Med hjälp av manifestfilen kan du ställa in varje regel på antingen
allow
,warn
ellererror
, till exempel{ "author":"Microsoft", "lints": [ { "lint": "needlessParens", "level": "allow" }, { "lint": "redundantSemicolons", "level": "warn" }, { "lint": "divisionByZero", "level": "error" } ] }
Du kan också använda manifestfilen för att definiera ett externt Q# projekt som ett beroende och fjärråtkomst till åtgärder och funktioner i det externa projektet. Mer information finns i Använda projekt som externa beroenden.
Q# projektkrav och egenskaper
Följande krav och konfigurationer gäller för alla Q# projekt.
Alla *.qs-filer som du vill ska ingå i projektet måste finnas under en mapp med namnet src, som måste finnas under rotmappen i Q#. När du skapar ett Q# projekt i VS Code
/src
skapas mappen automatiskt.Manifestfilen ska vara på samma nivå som src-mappen . När du skapar ett Q# projekt i VS Code skapas en minimal fil automatiskt.
Använd
import
instruktioner för att referera till åtgärder och funktioner från andra filer i projektet.import MyMathLib.*; //imports all the callables in the MyMathLib namespace ... Multiply(x,y);
eller refererar till dem individuellt med namnområdet
MyMathLib.Multiply(x,y);
Endast för Q# projekt
- Endast en *.qs-fil i ett Q# projekt kan ha en startpunkt definierad, definierad av en enda
Main()
åtgärd. - Filen *.qs med startpunktsdefinitionen kan finnas på valfri nivå under manifestfilen.
- Alla åtgärder eller funktioner som cachelagras från en *.qs-fil var som helst i Q# projektet visas i förutsägelsetext i VS Code.
- Om namnområdet för en vald åtgärd eller funktion inte har importerats ännu lägger VS Code automatiskt till den nödvändiga
import
instruktionen.
Steg för att skapa ett Q# projekt
De här stegen gäller för alla Q# projekt.
I VS Code-utforskaren högerklickar du på den mapp som du vill använda för rotmappen i Q# projektet och väljer Skapa Q# projekt, eller öppnar mappen och väljer Visa > kommandopalett >Q#: Skapa ett Q# projekt....
VS Code skapar en minimal manifestfil i mappen och lägger till en
/src
mapp med enMain.qs
mallfil.Redigera manifestfilen efter behov. Se Exempel på manifestfil.
Lägg till och organisera källfilerna Q#
/src
under mappen .Om du kommer Q# åt projektet från ett Python-program eller Jupyter Notebook anger du sökvägen till rotmappen med hjälp av
qsharp.init
. Det här exemplet förutsätter att ditt program finns i mappen /src i Q# projektet:qsharp.init(project_root = '../Teleportation_project')
Om du bara Q# använder filer i VS Code söker kompilatorn efter en manifestfil när du öppnar en Q# fil, fastställer rotmappen för projektet och söker sedan igenom undermappen efter *.qs-filer.
Kommentar
Du kan också skapa manifestfilen och /src
mappen manuellt i steg 2.
Exempelprojekt
Det här kvantteleporteringsprogrammet är ett exempel på ett Q# projekt baserat på den enskilda mappstruktur som visades tidigare och körs på den lokala simulatorn i VS Code. Information om hur du kör programmet på Azure Quantum-maskinvara eller tredjepartssimulatorer finns i Kom igång med Q# program och VSCode för steg för att kompilera programmet och ansluta till din Azure-arbetsyta.
I exemplet används den här katalogstrukturen:
- Teleportation_project
- qsharp.json
- Src
- Main.qs
- TeleportOperations
- TeleportLib.qs
- PrepareState
- PrepareStateLib.qs
Manifestfilen innehåller fälten författare och licenser :
{
"author":"Microsoft",
"license":"MIT"
}
Q# källfiler
Huvudfilen Main.qs innehåller startpunkten och refererar till TeleportOperations.TeleportLib
namnområdet från 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 definierar Teleport()
åtgärden och anropar PrepareBellPair()
åtgärden från 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);
}
Filen PrepareStateLib.qs innehåller en standardåtgärd som kan återanvändas för att skapa ett Bell-par.
operation PrepareBellPair(left : Qubit, right : Qubit) : Unit is Adj + Ctl {
H(left);
CNOT(left, right);
}
Köra programmen
Välj fliken för den miljö där du kör programmet.
Om du vill köra det här programmet öppnar du filen Main.qs i VS Code och väljer Kör.
Konfigurera Q# projekt som externa beroenden
Ett Q# projekt kan också konfigureras som ett externt beroende för andra projekt, ungefär som ett bibliotek, där funktionerna och åtgärderna i det externa Q# projektet görs tillgängliga för flera Q# projekt. Ett externt beroende kan finnas på en enhetsresurs eller publiceras till en offentlig GitHub-lagringsplats.
Om du vill använda ett Q# projekt som ett externt beroende måste du:
- Lägg till det externa projektet som ett beroende i manifestfilen för det anropande projektet.
- Om det externa projektet publiceras på GitHub lägger du till egenskapen "files" i manifestfilen för det externa projektet.
- Lägg till
export
instruktioner i det externa projektet. - Lägg till
import
instruktioner i det anropande projektet.
Konfigurera manifestfilerna
Externa Q# projekt kan finnas på en lokal resurs eller nätverksenhetsresurs eller publiceras till en offentlig GitHub-lagringsplats.
Manifestfilen för det anropande projektet
Om du vill lägga till ett beroende i ett externt projekt på en enhetsresurs definierar du beroendet i manifestfilen för det anropande projektet.
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"MyDependency": {
"path": "/path/to/project/folder/on/disk"
}
}
}
där "MyDependency" är en användardefinierad sträng som identifierar namnområdet när en åtgärd anropas. Om du till exempel skapar ett beroende med namnet "MyMathFunctions" anropar du en funktion från det beroendet med MyMathFunctions.MyFunction()
.
Så här lägger du till ett beroende till ett projekt som publiceras till en offentlig GitHub-lagringsplats
{
"author": "Microsoft",
"dependencies": {
"MyDependency": {
"github": {
"owner": "GitHubUser",
"repo": "GitHubRepoName",
"ref": "CommitHash",
"path": "/path/to/dependency"
}
}
}
Kommentar
För GitHub-beroenden refererar "ref" till en GitHub refspec. Microsoft rekommenderar att du alltid använder en incheckningshash, så att du kan förlita dig på en viss version av ditt beroende.
Manifestfilen för det externa projektet
Om ditt externa Q# projekt publiceras på en offentlig GitHub-lagringsplats måste du lägga till filegenskapen i manifestfilen för det externa projektet, inklusive alla filer som används i projektet.
{
"author": "Microsoft",
"license": "MIT",
"files": [ "src/MyMathFunctions.qs", "src/Strings/MyStringFunctions.qs" ]
}
Egenskapen "files" är valfri för ett externt projekt som importeras via "path"
(dvs. en lokal filsökvägsbaserad import). Det krävs endast för projekt som publicerats till GitHub.
Använda export-instruktionen
Om du vill göra funktioner och åtgärder i ett externt projekt tillgängliga för anropande projekt använder du -instruktionen export
. Du kan exportera valfritt eller alla anropsbara filer i filen. Jokerteckensyntax stöds inte. Du måste ange varje anropsbar fil som ska exporteras.
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;
Använda import-instruktionen
Från det anropande programmet använder import
du instruktioner för att göra objekt från ett externt beroende tillgängligt. import
-uttryck använder det namnområde som har definierats för beroendet i manifestfilen. Till exempel för det här beroendet
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"MyMathFunctions": {
"path": "/path/to/project/folder/on/disk"
}
}
}
du importerar anropsbara som
import MyMathFunctions.MyFunction; // imports "MyFunction()" from the namespace
...
-instruktionen import
stöder även jokerteckensyntax och alias
// 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;
Kommentar
Den för närvarande använda open
instruktionen i Q#, som används för att referera till bibliotek och namnområden, stöds fortfarande men kommer att bli inaktuell så småningom. Under tiden kan du uppdatera dina aktuella filer för att använda -instruktionen import
. Kan till exempel open Microsoft.Quantum.Diagnostics;
ersättas med import Microsoft.Quantum.Diagnostics.*;
.
Observera också att när du använder -instruktionen import
med standardbiblioteken Q# kan du förkorta rotnamnområdet till Std
. Kan till exempel import Microsoft.Quantum.Diagnostics.*;
skrivas som import Std.Diagnostics.*;
.
Exempel på externt projekt
I det här exemplet använder du samma teleporteringsprogram som i det tidigare exemplet, men separerar anropande program och anropsbara objekt i olika projekt.
Skapa två mappar på den lokala enheten, till exempel "Project_A" och "Project_B".
Skapa ett Q# projekt i varje mapp genom att följa stegen i Steg för att skapa ett Q# projekt.
I Project_A kopierar du följande kod till manifestfilen och redigerar sökvägen efter behov för Project_B
{ "author": "Microsoft", "license": "MIT", "dependencies": { "MyTeleportLib": { "path": "/Project_B" } } }
I Project_A kopierar du följande kod till 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); } }
I Project_B kopierar du följande kod till 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
Kommentar
Observera att åtgärden
PrepareBellPair
inte behöver exporteras eftersom den inte anropas direkt från programmet i Project_A. Eftersom den finns i det lokala omfånget för Project_B är den redan tillgänglig för åtgärdenTeleport
.Om du vill köra programmet öppnar du /Project_A/Main.qs i VS Code och väljer Kör.
Projekt och implicita namnområden
Om Q# ett namnområde inte har angetts i ett *.qs-program i projekt använder kompilatorn filnamnet som namnområde. Om du refererar till ett anropsbart från ett externt beroende använder du sedan syntaxen <dependencyName>.<namnområde>.<anropsbar>. Men om filen heter "Main.qs" förutsätter kompilatorn namnområdet och den anropande syntaxen är <dependencyName>.<anropsbar>, som i föregående exempel, import MyTeleportLib.Teleport
.
Eftersom det inte är ovanligt att ha flera projektfiler måste du ta hänsyn till rätt syntax när du refererar till anropsbara filer. Till exempel i ett projekt med följande filstruktur
- /Src
- Main.qs
- MathFunctions.qs
samtal till det externa beroendet skulle vara
import MyTeleportLib.MyFunction; // "Main" namespace is implied
import MyTeleportLib.MathFunctions.MyFunction; // "Math" namespace must be explicit
Mer information om namnområdesbeteende finns i Användarnamnrymder.