Jak tworzyć projekty i biblioteki niestandardowe oraz zarządzać nimi Q#
W tym artykule dowiesz się, jak tworzyć i udostępniać projekty oraz zarządzać nimiQ#. Q# projekty to struktury folderów z wieloma Q# plikami, które mogą uzyskiwać dostęp do operacji i funkcji zawartych w innych plikach. Projekty są przydatne do logicznego organizowania kodu źródłowego. Można również używać projektów jako bibliotek niestandardowych, do których można uzyskiwać dostęp ze źródeł zewnętrznych.
Wymagania wstępne
- Obszar roboczy usługi Azure Quantum w ramach subskrypcji platformy Azure. Aby utworzyć obszar roboczy, zobacz Tworzenie obszaru roboczego usługi Azure Quantum.
- Visual Studio Code z zainstalowanymi rozszerzeniami Azure Quantum Development Kit i Python.
- Konto usługi GitHub, jeśli planujesz opublikować projekt zewnętrzny w publicznym repozytorium GitHub.
Do uruchamiania programów w języku Python potrzebne są również następujące elementy:
- Środowisko Python ze zainstalowanymi Python i Pip.
- Pakiety Azure Quantum
qsharp
iazure-quantum
.
Jak Q# działają projekty
Q# Projekt zawiera plik manifestu Q# o nazwie qsharp.json i co najmniej jeden plik *.qs w określonej strukturze folderów. Gdy użytkownik otworzy plik *.qs w VS Code lub ustawi project_root
w pliku Jupyter Notebook lub Python, kompilator przeszukuje otaczającą hierarchię folderów w poszukiwaniu pliku manifestu i określa zakres projektu. Jeśli plik manifestu nie zostanie znaleziony, kompilator działa w trybie pojedynczego pliku. Można utworzyć projekt Q# ręcznie lub bezpośrednio w Visual Studio Code.
Projekt zewnętrzny Q# to standardowy Q# projekt, który znajduje się w innym katalogu lub w publicznym repozytorium GitHub i działa jako biblioteka niestandardowa. Projekt zewnętrzny używa export
instrukcji do zdefiniowania, do których funkcji i operacji można uzyskiwać dostęp za pomocą programów zewnętrznych. Programy definiują projekt zewnętrzny jako zależność w pliku manifestu i używają import
instrukcji w celu uzyskania dostępu do elementów (operacji, funkcji, struktur i przestrzeni nazw) w projekcie zewnętrznym. Aby uzyskać więcej informacji, zobacz Używanie projektów jako zależności zewnętrznych.
Definiowanie Q# projektu
Projekt Q# jest definiowany przez obecność pliku manifestu o nazwie qsharp.json i folderu src (który zawiera Q# pliki źródłowe), z których oba muszą znajdować się w folderze głównym projektu. W przypadku Q# programów i projektów Q# zewnętrznych kompilator automatycznie wykrywa folder projektu. W przypadku programów Python i Jupyter Notebooks należy za pomocą wywołania qsharp.init
określić folder Q# projektu. Jednak struktura folderów dla Q# projektu pozostaje taka sama dla wszystkich typów programów.
Definiowanie folderu projektu (Q# programy)
Po otwarciu pliku *.qs w programie VS Code, kompilator Q# przeszukuje w górę struktury folderów w poszukiwaniu pliku manifestu. Jeśli znajdzie plik manifestu, kompilator uwzględnia wszystkie Q# pliki w katalogu /src lub w dowolnym z jego podkatalogów. Elementy każdego pliku są udostępniane wszystkim innym plikom w projekcie.
Na przykład biorąc pod uwagę tę strukturę folderów:
-
Projekt_teleportacji
- qsharp.json
-
Src
- Main.qs
-
TeleportOperations
- TeleportLib.qs
-
PrepareState
- PrepareStateLib.qs
Po otwarciu pliku /src/TeleportOperation/PrepareState/PrepareStateLib.qs, kompilator:
- Sprawdza /src/TeleportOperation/PrepareState/ pod kątem qsharp.json.
- Sprawdza /src/TeleportOperation dla qsharp.json.
- Sprawdza /src pod kątem qsharp.json.
- Sprawdza / qsharp.json.
- Ustanawia / jako katalog główny projektu i włącza wszystkie pliki *.qs znajdujące się w katalogu głównym do projektu, zgodnie z ustawieniami określonymi w pliku manifestu.
Tworzenie pliku manifestu
Plik manifestu to prosty plik .json o nazwie qsharp.json , który opcjonalnie może zawierać pola autorów, licencji i lints . Minimalny realny plik manifestu to ciąg {}
. Podczas tworzenia Q# projektu w programie VS Code zostanie utworzony minimalny plik manifestu.
{}
Przykłady plików manifestu
Poniżej przedstawiono kilka przykładów sposobu, w jaki pliki manifestu mogą definiować zakres Q# projektu.
W tym przykładzie autor jest jedynym określonym polem i dlatego wszystkie pliki *.qs w tym katalogu i wszystkie jego podkatalogi są uwzględnione w projekcie Q# .
{ "author":"Microsoft", "license": "MIT" }
W projekcie Q# można również użyć pliku manifestu, aby dostosować ustawienia lintera w VS Code Q#. Domyślnie trzy reguły lintera to:
needlessParens
: default =allow
divisionByZero
: default =warn
redundantSemicolons
: default =warn
Za pomocą pliku manifestu można ustawić każdą regułę na
allow
,warn
luberror
, na przykład{ "author":"Microsoft", "lints": [ { "lint": "needlessParens", "level": "allow" }, { "lint": "redundantSemicolons", "level": "warn" }, { "lint": "divisionByZero", "level": "error" } ] }
Możesz również użyć pliku manifestu, aby zdefiniować projekt zewnętrzny Q# jako zależność oraz zdalnie uzyskać dostęp do operacji i funkcji w tym projekcie zewnętrznym. Aby uzyskać więcej informacji, zobacz Używanie projektów jako zależności zewnętrznych.
Q# wymagania i właściwości projektu
Następujące wymagania i konfiguracje mają zastosowanie do wszystkich Q# projektów.
Wszystkie pliki *.qs, które chcesz uwzględnić w projekcie, muszą znajdować się w folderze o nazwie src, który musi znajdować się w folderze głównym folderu Q#. Podczas tworzenia projektu Q# w programie VS Code folder
/src
jest automatycznie tworzony.Plik manifestu powinien być na tym samym poziomie co folder src . Podczas tworzenia Q# projektu w programie VS Code jest tworzony automatycznie minimalny plik.
Użyj
import
do odwoływania się do operacji i funkcji z innych plików w projekcie.import MyMathLib.*; //imports all the callables in the MyMathLib namespace ... Multiply(x,y);
lub odwoływanie się do nich indywidualnie za pomocą przestrzeni nazw
MyMathLib.Multiply(x,y);
Tylko na projekty Q#
- Tylko jeden plik *.qs w projekcie Q# może mieć zdefiniowany punkt wejścia zdefiniowany przez jedną
Main()
operację. - Plik *.qs z definicją punktu wejścia może znajdować się na dowolnym poziomie poniżej pliku manifestu.
- Każda operacja lub funkcja buforowana z pliku *.qs w dowolnym miejscu projektu Q# jest wyświetlana w tekście predykcyjnym w programie VS Code.
- Jeśli przestrzeń nazw dla wybranej operacji lub funkcji nie jest jeszcze importowana, program VS Code automatycznie dodaje niezbędną
import
instrukcję.
Kroki tworzenia Q# projektu
Te kroki dotyczą wszystkich Q# projektów.
W Eksploratorze plików programu VS Code kliknij prawym przyciskiem myszy folder, którego chcesz użyć dla folderu Q# głównego projektu, a następnie wybierz polecenie Utwórz Q# projekt lub otwórz folder i wybierz polecenie Wyświetl > paletę >Q#Q# poleceń: Utwórz projekt....
Program VS Code tworzy minimalny plik manifestu w folderze i tworzy folder
/src
z plikiem szablonuMain.qs
.Edytuj plik manifestu zgodnie z potrzebami. Zobacz Przykłady plików manifestu.
Dodaj i organizuj Q# pliki źródłowe w folderze
/src
.Jeśli uzyskujesz dostęp do projektu Q# z programu Python lub notesu Jupyter, ustaw ścieżkę folderu głównego przy użyciu
qsharp.init
. W tym przykładzie przyjęto założenie, że program znajduje się w folderze Q# /src projektu:qsharp.init(project_root = '../Teleportation_project')
Jeśli używasz tylko Q# plików w programie VS Code, podczas otwierania pliku Q# kompilator wyszukuje plik manifestu, określa folder główny projektu, a następnie skanuje podfolder plików *.qs.
Uwaga
Możesz również ręcznie utworzyć plik manifestu /src
i folder w kroku 2.
Przykładowy projekt
Ten program teleportacji kwantowej jest przykładem Q# projektu opartego na przedstawionej wcześniej strukturze pojedynczego folderu i działa w symulatorze lokalnym w programie VS Code. Aby uruchomić program na sprzęcie azure Quantum lub symulatorach innych firm, zobacz Rozpoczynanie pracy z programami Q# i programem VSCode, aby uzyskać instrukcje kompilowania programu i nawiązywania połączenia z obszarem roboczym platformy Azure.
W przykładzie użyto tej struktury katalogów:
-
Projekt_Teleportacja
- qsharp.json
-
Src
- Main.qs
-
TeleportOperations
- TeleportLib.qs
-
PrepareState
- PrepareStateLib.qs
Plik manifestu zawiera pola autorów i licencji:
{
"author":"Microsoft",
"license":"MIT"
}
Q# pliki źródłowe
Główny plik Main.qs zawiera punkt wejścia i odwołuje się do przestrzeni nazw TeleportOperations.TeleportLib
z pliku 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 definiuje operację Teleport()
i wywołuje operację PrepareBellPair()
z pliku 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);
}
Plik PrepareStateLib.qs zawiera standardową operację wielokrotnego użytku w celu utworzenia pary bell.
operation PrepareBellPair(left : Qubit, right : Qubit) : Unit is Adj + Ctl {
H(left);
CNOT(left, right);
}
Uruchamianie programów
Wybierz kartę środowiska, w którym program jest uruchomiony.
Aby uruchomić ten program, otwórz plik Main.qs w programie VS Code i wybierz pozycję Uruchom.
Konfigurowanie Q# projektów jako zależności zewnętrznych
Projekt Q# można również skonfigurować jako zależność zewnętrzną dla innych projektów, działając podobnie jak biblioteka, w której funkcje i operacje w projekcie zewnętrznym Q# są udostępniane wielu Q# projektom. Zależność zewnętrzna może znajdować się w udziale dysku lub opublikowanym w publicznym repozytorium GitHub.
Aby użyć Q# projektu jako zależności zewnętrznej, musisz:
- Dodaj projekt zewnętrzny jako zależność w pliku manifestu projektu wywołującego.
- Jeśli projekt zewnętrzny zostanie opublikowany w usłudze GitHub, dodaj właściwość "files" do pliku manifestu projektu zewnętrznego.
- Dodaj
export
deklaracje do projektu zewnętrznego. - Dodaj
import
wyrażenia do projektu wywołującego.
Konfigurowanie plików manifestu
Projekty zewnętrzne Q# mogą znajdować się w udziale dysku lokalnym lub sieciowym albo publikować je w publicznym repozytorium GitHub.
Plik manifestu projektu wywołującego
Aby dodać zależność do projektu zewnętrznego w udziale dysku, zdefiniuj zależność w pliku manifestu projektu wywołującego.
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"MyDependency": {
"path": "/path/to/project/folder/on/disk"
}
}
}
gdzie "MyDependency" to ciąg zdefiniowany przez użytkownika, który identyfikuje przestrzeń nazw podczas wywoływania operacji. Jeśli na przykład utworzysz zależność o nazwie "MyMathFunctions", wywołasz funkcję z tej zależności za pomocą polecenia MyMathFunctions.MyFunction()
.
Aby dodać zależność do projektu opublikowanego w publicznym repozytorium GitHub
{
"author": "Microsoft",
"dependencies": {
"MyDependency": {
"github": {
"owner": "GitHubUser",
"repo": "GitHubRepoName",
"ref": "CommitHash",
"path": "/path/to/dependency"
}
}
}
Uwaga
W przypadku zależności GitHub "ref" odnosi się do GitHub refspec. Firma Microsoft zaleca zawsze używanie skrótu zatwierdzenia, dzięki czemu można polegać na określonej wersji zależności.
Plik manifestu projektu zewnętrznego
Jeśli projekt zewnętrzny Q# jest publikowany w publicznym repozytorium GitHub, musisz dodać właściwość files do pliku manifestu projektu zewnętrznego, w tym wszystkie pliki używane w projekcie.
{
"author": "Microsoft",
"license": "MIT",
"files": [ "src/MyMathFunctions.qs", "src/Strings/MyStringFunctions.qs" ]
}
Właściwość "files" jest opcjonalna dla projektu zewnętrznego importowanego za pośrednictwem "path"
(czyli lokalnego importu opartego na ścieżce plików). Jest to wymagane tylko w przypadku projektów publikowanych w usłudze GitHub.
Korzystanie z instrukcji export
Aby udostępnić funkcje i operacje w projekcie zewnętrznym do wywoływania projektów, należy użyć instrukcji export
. W pliku można wyeksportować dowolne lub wszystkie obiekty wywołujące. Składnia symboli wieloznacznych nie jest obsługiwana. Należy określić każdy element wywoływalny do wyeksportowania.
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;
Używanie instrukcji 'import'
Z poziomu programu wywołującego używa się instrukcji import
, aby umożliwić dostęp do elementów z zewnętrznej zależności.
import
instrukcje używają przestrzeni nazw zdefiniowanej dla zależności w pliku manifestu. Na przykład dla tej zależności
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"MyMathFunctions": {
"path": "/path/to/project/folder/on/disk"
}
}
}
importujesz wywoływalne jako
import MyMathFunctions.MyFunction; // imports "MyFunction()" from the namespace
...
Instrukcja import
obsługuje również składnię kart wieloznacznych i aliasów.
// 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;
Uwaga
Obecnie używana open
instrukcja w Q# pliku, która jest używana do odwołania się do bibliotek i przestrzeni nazw, nadal jest obsługiwana, ale ostatecznie zostanie wycofana. W międzyczasie możesz opcjonalnie zaktualizować bieżące pliki, aby użyć instrukcji import
. Na przykład open Microsoft.Quantum.Diagnostics;
można zastąpić import Microsoft.Quantum.Diagnostics.*;
.
Należy również pamiętać, że w przypadku używania instrukcji import
z bibliotekami standardowymi Q# można skrócić przestrzeń nazw katalogu głównego do Std
. Można na przykład import Microsoft.Quantum.Diagnostics.*;
zapisać jako import Std.Diagnostics.*;
.
Przykładowy projekt zewnętrzny
W tym przykładzie użyjesz tego samego programu teleportacji co w poprzednim przykładzie, ale oddzielisz program wywołujący i wywoływane elementy do różnych projektów.
Utwórz dwa foldery na dysku lokalnym, na przykład "Project_A" i "Project_B".
Q# Utwórz projekt w każdym folderze, wykonując kroki opisane w temacie Kroki tworzenia Q# projektu.
W programie wywołującym Project_A skopiuj następujący kod do pliku manifestu, edytując ścieżkę zgodnie z potrzebami Project_B
{ "author": "Microsoft", "license": "MIT", "dependencies": { "MyTeleportLib": { "path": "/Project_B" } } }
W Project_A skopiuj następujący kod do pliku 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); } }
W Project_B skopiuj następujący kod do pliku 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
Uwaga
Należy pamiętać, że operacja
PrepareBellPair
nie musi być eksportowana, ponieważ nie jest wywoływana bezpośrednio z Twojego programu w Project_A. Ponieważ znajduje się on w lokalnym zakresie Project_B, jest już dostępny przez operacjęTeleport
Aby uruchomić program, otwórz plik /Project_A/Main.qs w programie VS Code i wybierz pozycję Uruchom.
Projekty i niejawne przestrzenie nazw
Jeśli w Q# projektach nie określono przestrzeni nazw w programie *.qs, kompilator używa nazwy pliku jako przestrzeni nazw. Odwoływanie się do elementu wywoływalnego z zewnętrznej zależności używa składni <dependencyName>.<przestrzeń_nazw>.<funkcja>. Jeśli jednak plik nosi nazwę "Main.qs", kompilator zakłada przestrzeń nazw, a składnia wywołująca to <dependencyName>.<wywoływane>, tak jak w poprzednim przykładzie, import MyTeleportLib.Teleport
.
Ponieważ nie jest rzadkością mieć wiele plików projektu, należy uwzględnić poprawną składnię podczas odwoływania się do elementów wywołujących. Na przykład w projekcie z następującą strukturą plików
- /src
- Main.qs
- MathFunctions.qs
wywołania zależności zewnętrznej byłyby następujące
import MyTeleportLib.MyFunction; // "Main" namespace is implied
import MyTeleportLib.MathFunctions.MyFunction; // "Math" namespace must be explicit
Aby uzyskać więcej informacji na temat zachowania przestrzeni nazw, zobacz Przestrzenie nazw użytkowników.