Jak tworzyć projekty i biblioteki niestandardowe oraz zarządzać nimi Q#

Z tego artykułu dowiesz się, jak tworzyć i udostępniać projekty oraz zarządzać nimi Q# . Q# Projekt to struktura folderów z wieloma Q# plikami, które mogą uzyskiwać dostęp do operacji i funkcji innych. Projekty ułatwiają logiczne organizowanie kodu źródłowego. Można również używać projektów jako bibliotek niestandardowych, do których można uzyskać dostęp z zewnętrznych źródeł.

Wymagania wstępne

Aby uruchomić Python programów, potrzebne są również następujące elementy:

  • Zainstalowane środowisko Python, które zawiera Python i Pip.

  • Pakiet qdkPython z dodatkiem azure .

    python -m pip install --upgrade "qdk[azure]"
    

Jak Q# działają projekty

Q# Projekt zawiera plik manifestu Q# o nazwie qsharp.json, i co najmniej jeden plik .qs i .qsc w określonej strukturze folderów. Projekt można utworzyć Q# ręcznie lub bezpośrednio w pliku VS Code.

Po otwarciu pliku .qs lub .qsc w programie VS Code, kompilator przeszukuje otaczającą hierarchię folderów w poszukiwaniu pliku manifestu i określa zakres projektu. Jeśli kompilator nie znajdzie pliku manifestu, kompilator działa w trybie pojedynczego pliku.

Po ustawieniu project_root w folderze Jupyter Notebook lub Python kompilator wyszukuje plik manifestu w folderze project_root.

Zewnętrzny projekt Q# jest standardowym projektem Q#, 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 definiowania funkcji i operacji, które są dostępne przez programy zewnętrzne. Programy definiują projekt zewnętrzny jako zależność w pliku manifestu i używają import instrukcji w celu uzyskania dostępu do elementów w projekcie zewnętrznym, takich jak operacje, funkcje, struktury i przestrzenie nazw. 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 qsharp.json oraz folderu src, który musi znajdować się w folderze głównym projektu. Folder src zawiera Q# pliki źródłowe. W przypadku Q# programów i projektów Q# zewnętrznych kompilator automatycznie wykrywa folder projektu. W przypadku Python programów i Jupyter Notebook plików należy określić Q# folderu projektu wywołaniem qsharp.init. Jednak struktura folderów projektu Q# jest taka sama dla wszystkich typów programów.

Struktura folderów i hierarchia Q# projektu.

Definiowanie folderu projektu dla Q# programów

Po otwarciu pliku .qs w programie VS Code, kompilator Q# przeszukuje strukturę folderów w górę, aby znaleźć plik manifestu. Jeśli kompilator znajdzie plik manifestu, uwzględnia wszystkie pliki Q# znajdujące się w katalogu /src i jego podkatalogach. Elementy zdefiniowane w każdym pliku stają się dostępne dla wszystkich innych plików w projekcie.

Rozważmy na przykład następującą strukturę folderów:

  • Projekt_teleportacji
    • qsharp.json
    • Src
      • Main.qs
      • TeleportOperations
        • TeleportLib.qs
        • PrepareState
          • PrepareStateLib.qs

Po otwarciu pliku /src/TeleportOperation/PrepareState/PrepareStateLib.qsQ# kompilator wykonuje następujące czynności:

  1. Sprawdza /src/TeleportOperation/PrepareState/ względem qsharp.json.
  2. Sprawdza /src/TeleportOperation względem qsharp.json.
  3. Sprawdza /src względem qsharp.json.
  4. Sprawdza /Teleportation_project wraz z qsharp.json i znajduje plik.
  5. Ustanawia /Teleportation_project jako katalog główny projektu i zawiera wszystkie pliki .qs oraz .qsc w katalogu /src w projekcie. Jeśli plik manifestu.

Uwaga

Jeśli dołączasz jawne odwołania do ścieżek plików .qs i .qsc w qsharp.json, kompilator ładuje te pliki i nie przechodzi przez proces automatycznego odnajdywania. Jawne odwołania do ścieżki pliku są niezbędne tylko wtedy, gdy zdefiniujesz bibliotekę do załadowania z dokumentacji usługi Git.

Tworzenie pliku manifestu

Plik manifestu to plik JSON o nazwie qsharp.json , który może zawierać opcjonalne authorpola , licensei lints . Minimalny realny plik manifestu to ciąg {}. Podczas tworzenia Q# projektu w programie VS Codezostanie utworzony minimalny plik manifestu.

{}

Przykłady plików manifestu

W poniższych przykładach pokazano, jak pliki manifestu Q# definiują zakres projektu.

  • W tym przykładzie author jest jedynym określonym polem, więc wszystkie .qs pliki w tym katalogu i jego podkatalogach są uwzględnione w projekcie Q# .

    {
        "author":"Microsoft"
    }
    
  • W projekcie Q# można również użyć pliku manifestu, aby dostosować ustawienia Lintera VS CodeQ#. Domyślnie trzy reguły lintera to:

    • needlessParens: default = allow

    • divisionByZero: default = warn

    • redundantSemicolons: default = warn

      Każdą regułę w pliku manifestu można ustawić na allow, warnlub error. 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 .qs pliki, które mają zostać uwzględnione w projekcie, muszą znajdować się w folderze o nazwie src, który musi znajdować się w folderze Q# głównym projektu. Podczas tworzenia projektu Q# w VS Code, folder /src jest tworzony automatycznie.

  • Plik manifestu src powinien być na tym samym poziomie co folder. Podczas tworzenia Q# projektu w programie VS Codezostanie automatycznie utworzony minimalny plik manifestu.

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

    Możesz też odwołać się do nich indywidualnie, używając przestrzeni nazw.

    MyMathLib.Multiply(x,y); 
    

Tylko dla Q# projektów

  • Operację punktu wejścia można zdefiniować tylko w jednym .qs pliku w Q# projekcie, a domyślnie jest to operacja Main().
  • Należy umieścić .qs plik z definicją punktu wejścia na poziomie katalogu projektu poniżej pliku manifestu.
  • Wszystkie operacje i funkcje w projekcie Q# , które są buforowane z wyświetlacza w tekście predykcyjnym .qs w programie VS Code.
  • Jeśli przestrzeń nazw dla wybranej operacji lub funkcji nie zostanie jeszcze zaimportowana, VS Code automatycznie doda wymaganą import instrukcję.

Jak utworzyć Q# projekt

Aby utworzyć Q# projekt, wykonaj następujące kroki:

  1. W Eksploratorze VS Code plików przejdź do folderu, którego chcesz użyć jako folderu głównego projektu Q# .

  2. Otwórz menu Widok i wybierz pozycję Paleta poleceń.

  3. Wprowadź QDK: Utwórz projekt Q#. VS Code Tworzy minimalny plik manifestu w folderze i dodaje /src folder z plikiem szablonu Main.qs .

  4. Edytuj plik manifestu dla projektu. Zobacz Przykłady plików manifestu.

  5. Dodaj i organizuj Q# pliki źródłowe w folderze /src .

  6. Jeśli uzyskujesz dostęp do projektu Q# z programu Python lub Jupyter Notebook, ustaw ścieżkę folderu root z qsharp.init. W tym przykładzie przyjęto założenie, że program znajduje się w /src folderze Q# projektu:

    qsharp.init(project_root = '../Teleportation_project')
    
  7. Jeśli używasz tylko Q# plików w VS Codeprogramie , kompilator wyszukuje plik manifestu podczas otwierania Q# pliku i określa folder główny projektu. Następnie kompilator skanuje /src i jego podkatalogi pod kątem plików .qs i .qsc.

Uwaga

Zamiast tego możesz ręcznie utworzyć plik manifestu /src i folder.

Przykładowy projekt

Ten program teleportacji kwantowej jest przykładem Q# projektu uruchamianego w symulatorze lokalnym w VS Code. pl-PL: Aby uruchomić program na sprzęcie Azure Quantum lub symulatorach innych firm, zobacz Rozpocznij korzystanie z programów Q# i VS Code, aby uzyskać instrukcje kompilowania programu i połączenia się z obszarem roboczym Azure Quantum.

Ten przykład ma następującą strukturę katalogów:

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

Plik 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ę dla środowiska, w którym uruchamiasz program.

Aby uruchomić ten program, otwórz plik Main.qs w VS Code, a następnie wybierz Uruchom.

Konfigurowanie Q# projektów jako zależności zewnętrznych

Projekty można skonfigurować Q# jako zależność zewnętrzną dla innych projektów, podobnie jak biblioteka, aby funkcje i operacje w projekcie zewnętrznym Q# były dostępne dla innych Q# projektów. Zależność zewnętrzna może znajdować się w udziale dysku lub być publikowana 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 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

Zewnętrzne projekty Q# mogą znajdować się w udziale dysku lokalnym lub sieciowym lub można je opublikować 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"
        }
    }
}

W wcześniejszym pliku manifestu MyDependency jest ciągiem zdefiniowanym przez użytkownika, który identyfikuje przestrzeń nazw podczas wywoływania operacji. Jeśli na przykład utworzysz zależność o nazwie MyMathFunctions, możesz wywołać funkcję z tej zależności za pomocą polecenia MyMathFunctions.MyFunction().

Aby dodać zależność do projektu opublikowanego w publicznym repozytorium GitHub, użyj następującego przykładowego pliku manifestu:

{
    "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. Microsoft Zaleca, aby zawsze używać hash zatwierdzenia, aby można było polegać na określonej wersji zależności.

Plik manifestu projektu zewnętrznego

Jeśli zewnętrzny projekt Q# jest publikowany w publicznym repozytorium GitHub, należy dodać właściwość files do pliku manifestu projektu zewnętrznego, w tym wszystkie pliki używane przez projekt.

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

Właściwość files jest opcjonalna dla zewnętrznego projektu importowanego przy użyciu "path" lokalnego importu opartego na ścieżce pliku. Właściwość files jest wymagana tylko dla projektów publikowanych w GitHub.

Użyj instrukcji export

Aby udostępnić funkcje i operacje w projekcie zewnętrznym do wywoływania projektów, użyj instrukcji export . W pliku można wyeksportować dowolne lub wszystkie obiekty wywołujące. Nie można użyć symboli wieloznacznych, dlatego należy określić każde wywołanie, które chcesz wyeksportować.

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żyj instrukcji import

Aby udostępnić elementy z zależności zewnętrznej, użyj import instrukcji z programu wywołującego. Instrukcja import używa przestrzeni nazw zdefiniowanej dla zależności w pliku manifestu.

Rozważmy na przykład zależność w następującym pliku manifestu:

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

Zaimportuj obiekty wywołujące przy użyciu następującego kodu:

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

...

Instrukcja import obsługuje również składnię symboli wieloznacznych i aliasy.

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

Przykładowy projekt zewnętrzny

W tym przykładzie użyj tego samego programu teleportacji co w poprzednim przykładzie, ale rozdziel program wywołujący i obiekty wywołujące do różnych projektów.

  1. Utwórz dwa foldery na dysku lokalnym, na przykład Project_A i Project_B.

  2. Q# Utwórz projekt w każdym folderze. Aby uzyskać szczegółowe informacje, zobacz kroki opisane w temacie How to create a project ( Q# Jak utworzyć projekt).

  3. W programie wywołującym Project_A, skopiuj następujący kod do pliku manifestu, ale zmodyfikuj ścieżkę zgodnie z potrzebami dla Project_B.

    {
      "author": "Microsoft",
      "license": "MIT",
      "dependencies": {
        "MyTeleportLib": {
          "path": "/Project_B" 
          }
        }
      }    
    
  4. W Project_Apliku skopiuj następujący kod do Main.qspliku :

    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. W Project_Bpliku skopiuj następujący kod do Main.qspliku :

        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

    Nie musisz eksportować operacji PrepareBellPair, jeśli twój program w Project_A nie wywołuje tej operacji bezpośrednio. Operacja PrepareBellPair jest już dostępna przez operację Teleport , ponieważ PrepareBellPair znajduje się w lokalnym zakresie Project_B.

  6. Aby uruchomić program, otwórz plik /Project_A/Main.qs i VS Code wybierz polecenie Uruchom.

Projekty i niejawne przestrzenie nazw

W Q# projektach, jeśli nie określisz przestrzeni nazw w .qs programie, kompilator używa nazwy pliku jako przestrzeni nazw. Następnie, gdy odwołujesz się do elementu wywoływalnego z zależności zewnętrznej, należy użyć składni <dependencyName>.<namespace>.<callable>. Jeśli jednak plik ma nazwę Main.qs, kompilator zakłada, że przestrzeń nazw i składnia wywołująca to <dependencyName>.<callable>. Na przykład import MyTeleportLib.Teleport.

Ponieważ może istnieć wiele plików projektu, musisz uwzględnić poprawną składnię podczas odwołwania się do elementów wywołujących. Rozważmy na przykład projekt z następującą strukturą plików:

  • /Src
    • Main.qs
    • MathFunctions.qs

Poniższy kod wykonuje wywołania zależności zewnętrznej:

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.