Создание проектов и пользовательских библиотек и управление ими Q#

Из этой статьи вы узнаете, как создавать, управлять и совместно использовать Q# проекты. Q# Проект — это структура папок с несколькими Q# файлами, которые могут получить доступ к операциям и функциям друг друга. Проекты помогают логически упорядочивать исходный код. Вы также можете использовать проекты в качестве пользовательских библиотек, к которым можно получить доступ из внешних источников.

Предварительные требования

  • Рабочая область Azure Quantum в подписке Azure. Сведения о создании рабочей области см. в разделе Create Azure Quantum workspace.
  • Visual Studio Code (VS Code) с установленными расширениями Microsoft Quantum Development Kit (QDK) и Python.
  • Чтобы опубликовать внешний проект в общедоступном репозитории GitHub, необходимо иметь учетную запись GitHub.

Чтобы запустить программы Python, вам также потребуется:

  • Среда Python с установленными Python и Pip.

  • Пакет qdkPython с дополнительным компонентом azure.

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

Как Q# работают проекты

Проект Q# содержит файл манифеста Q# с именем qsharp.json, а также один или несколько .qs.qsc файлов в указанной структуре папок. Вы можете создать проект вручную Q# или непосредственно в VS Code.

Когда вы открываете файл .qs или файл .qsc в VS Code, компилятор ищет иерархию каталогов папок для файла манифеста и определяет масштаб проекта. Если компилятор не находит файл манифеста, компилятор работает в одном режиме файлов.

При установке project_root в файле Jupyter Notebook или Python компилятор ищет файл манифеста в папке project_root.

Внешний проект Q# — это стандартный проект Q#, расположенный в другом каталоге или в общедоступном репозитории GitHub, и выступает в качестве пользовательской библиотеки. Внешний проект использует export выражения для определения функций и операций, доступных внешним программам. Программы определяют внешний проект как зависимость в файле манифеста и используют import инструкции для доступа к элементам во внешнем проекте, таким как операции, функции, структуры и пространства имен. Дополнительные сведения см. в разделе "Использование проектов в качестве внешних зависимостей".

Q# Определение проекта

Q# Проект определяется наличием qsharp.json файла манифеста и src папки, оба из которых должны находиться в корневой папке проекта. Папка src содержит исходные Q# файлы. Для Q# программ и внешних проектов Q# компилятор автоматически обнаруживает папку проекта. Для Python программ и Jupyter Notebook файлов необходимо указать папку проекта Q# с помощью вызова qsharp.init. Однако структура папок проекта Q# одинакова для всех типов программ.

Структура папок и иерархия для Q# проекта.

Определение папки проекта для Q# программ

При открытии файла .qs в VS Code компилятор Q# выполняет поиск вверх по структуре папок для файла манифеста. Если компилятор находит файл манифеста, компилятор содержит все Q# файлы в каталоге /src и его подкаталогах. Элементы, определенные в каждом файле, становятся доступными для всех остальных файлов в проекте.

Например, рассмотрим следующую структуру папок:

  • Проект_по_телепортации
    • qsharp.json
    • src
      • Main.qs
      • TeleportOperations
        • TeleportLib.qs
        • PrepareState
          • PrepareStateLib.qs

При открытии файла /src/TeleportOperation/PrepareState/PrepareStateLib.qsQ# компилятор выполняет следующие действия:

  1. Проверяет /src/TeleportOperation/PrepareState/ на qsharp.json.
  2. Проверяет /src/TeleportOperation на qsharp.json.
  3. Проверяет /src на qsharp.json.
  4. Проверяет /Teleportation_projectqsharp.json и находит файл.
  5. Использует /Teleportation_project в качестве корневого каталога проекта и включает в проект все файлы .qs и .qsc, находящиеся в каталоге /src. Если файл манифеста существует.

Примечание.

Если вы включаете явные ссылки на пути к файлам .qs и .qsc в qsharp.json, компилятор загружает эти файлы и не проходит процесс автоматического обнаружения. Явные ссылки на путь к файлам необходимы только при определении библиотеки для загрузки из ссылки на Git.

Создание файла манифеста

Файл манифеста — это JSON-файл с именемqsharp.json, который может включать необязательные authorlicenseполя и lints поля. Минимальный жизнеспособный файл манифеста — это строка {}. При создании проекта Q# в VS Code создается минимальный файл манифеста.

{}

Примеры файлов манифеста

В следующих примерах показано, как файлы манифеста Q# определяют область проекта.

  • В этом примере author является единственным указанным полем, поэтому все .qs файлы в этом каталоге и его подкаталогах включены в Q# проект.

    {
        "author":"Microsoft"
    }
    
  • В проекте Q# также можно использовать файл манифеста для точной настройки параметров VS CodeQ# Linter. По умолчанию три правила Linter:

    • needlessParens: default = allow

    • divisionByZero: default = warn

    • redundantSemicolons: default = warn

      Для каждого правила в файле манифеста можно задать значение allow, warnили error. Рассмотрим пример.

      {
          "author":"Microsoft",
          "lints": [
              {
                "lint": "needlessParens",
                "level": "allow"
              },
              {
                "lint": "redundantSemicolons",
                "level": "warn"
              },
              {
                "lint": "divisionByZero",
                "level": "error"
              }
            ]
      }
      
  • Вы также можете использовать файл манифеста для определения внешнего проекта как зависимости и удаленного доступа к операциям и функциям в этом внешнем Q# проекте. Дополнительные сведения см. в разделе "Использование проектов в качестве внешних зависимостей".

Q# Требования к проекту и свойства

Следующие требования и конфигурации применяются ко всем Q# проектам.

  • Все .qs файлы, которые необходимо включить в проект, должны находиться в папке с именем src, которая должна находиться в корневой Q# папке проекта. При создании проекта Q# в VS Code папка /src создается автоматически.

  • Файл манифеста должен находиться на том же уровне, что и папка src. При создании проекта в Q#автоматически создается минимальный VS Code файл манифеста.

  • Используйте import инструкции для ссылки на операции и функции из других файлов в проекте.

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

    Или вы можете ссылаться на них по отдельности, используя пространство имен.

    MyMathLib.Multiply(x,y); 
    

Только для Q# проектов

  • Вы можете определить операцию точки входа только в одном .qs файле в проекте Q#, который по умолчанию выполняет операцию Main().
  • Необходимо поместить .qs файл с определением точки входа на уровне каталога проекта ниже файла манифеста.
  • Все операции и функции в проекте Q#, которые кэшируются из отображения .qs, появляются в автозаполнении текста VS Code.
  • Если пространство имен для выбранной операции или функции еще не импортировано, VS Code автоматически добавляет необходимую import инструкцию.

Как создать проект Q#

Чтобы создать Q# проект, выполните следующие действия.

  1. В проводнике файлов перейдите VS Code в папку, которую хотите использовать в качестве корневой папки для Q# проекта.

  2. Откройте меню "Вид " и выберите палитру команд.

  3. Ввод QDK: создание Q# проекта. VS Code создает минимальный файл манифеста в папке и добавляет /src папку с файлом Main.qs шаблона.

  4. Измените файл манифеста для проекта. См. примеры файлов манифеста.

  5. Добавьте и упорядочьте Q# исходные файлы в папке /src.

  6. Если вы обращаетесь к проекту Q# из программы Python или Jupyter Notebook, задайте путь к корневой папке с qsharp.init. В этом примере предполагается, что программа находится в /src папке Q# проекта:

    qsharp.init(project_root = '../Teleportation_project')
    
  7. Если вы используете только файлы Q#, компилятор VS Code ищет файл манифеста при открытии файла Q# и определяет корневую папку проекта. Затем компилятор сканирует /src и его подкаталоги для .qs и .qsc файлов.

Примечание.

Вместо этого можно создать файл манифеста и папку /src вручную.

Пример проекта

Эта программа квантовой телепортации является примером Q# проекта, работающего на локальном симуляторе VS Code. Чтобы запустить программу на аппаратном обеспечении Azure Quantum или сторонних симуляторах, см. статью Начало работы с программами Q# и VS Code, чтобы выполнить компиляцию вашей программы и подключиться к рабочей области Azure Quantum.

В этом примере имеется следующая структура каталогов:

  • Проект_по_телепортации
    • qsharp.json
    • src
      • Main.qs
      • TeleportOperations
        • TeleportLib.qs
        • PrepareState
          • PrepareStateLib.qs

Файл манифеста содержит поля автора и лицензии :

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

Q# исходные файлы

Основной файл Main.qs содержит точку входа TeleportOperations.TeleportLib и ссылается на пространство имен из 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 определяет Teleport операцию и вызывает PrepareBellPair операцию из 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);
    }

Файл PrepareStateLib.qs содержит стандартную операцию, подходящую для многократного использования, для создания пары Белла.

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

Запуск программ

Выберите вкладку для среды, в которой выполняется программа.

Чтобы запустить эту программу, откройте Main.qs файл VS Code и нажмите кнопку "Выполнить".

Настройте Q# проекты, являющиеся внешними зависимостями

Вы можете сконфигурировать Q# проекты как внешнюю зависимость для других проектов, аналогично библиотеке, чтобы функции и операции во внешнем Q# проекте были доступны другим Q# проектам. Внешняя зависимость может находиться на общей папке диска или публиковаться в общедоступном GitHub репозитории.

Чтобы использовать Q# проект в качестве внешней зависимости, необходимо:

  • Добавьте внешний проект в качестве зависимости в файл манифеста вызывающего проекта.
  • Если внешний проект опубликован в GitHub, добавьте свойство files в файл манифеста внешнего проекта.
  • Добавьте export инструкции во внешний проект.
  • Добавьте import инструкции в вызывающий проект.

Настройка файлов манифеста

Внешние проекты Q# могут находиться на локальном или сетевом диске или публиковать их в общедоступном репозитории GitHub.

Файл манифеста вызывающего проекта

Чтобы добавить зависимость во внешний проект в общую папку диска, определите зависимость в файле манифеста вызывающего проекта.

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

В предыдущем файле MyDependency манифеста — это определяемая пользователем строка, определяющая пространство имен при вызове операции. Например, если вы создаете зависимость, названную MyMathFunctions, то вы можете вызвать функцию из этой зависимости с помощью MyMathFunctions.MyFunction().

Чтобы добавить зависимость в проект, опубликованный в общедоступном репозитории GitHub, используйте следующий пример файла манифеста:

{
    "author": "Microsoft",
    "dependencies": {
        "MyDependency": {
            "github": {
                "owner": "GitHubUser",
                "repo": "GitHubRepoName",
                "ref": "CommitHash",
                "path": "/path/to/dependency"
            }
        }
    }
}

Примечание.

Для зависимостей GitHub ref относится к GitHub refspec. Microsoft рекомендует всегда использовать коммит-хеш, чтобы вы могли полагаться на конкретную версию зависимости.

Файл манифеста внешнего проекта

Если внешний проект Q# публикуется в общедоступном репозитории GitHub, необходимо добавить свойство files в файл манифеста внешнего проекта, включая все файлы, используемые проектом.

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

Это свойство files является необязательным для внешнего проекта, импортируемого через "path" с использованием локального импорта, основанного на пути к файлу. Свойство files требуется только для проектов, опубликованных в GitHub.

Используйте инструкцию export

Чтобы сделать функции и операции во внешнем проекте доступными для вызова проектов, используйте инструкцию export . Вы можете экспортировать любые или все вызываемые объекты в файле. Нельзя использовать подстановочный символ, поэтому необходимо указать каждый вызываемый объект, который требуется экспортировать.

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;

Используйте инструкцию import

Чтобы сделать элементы из внешней зависимости доступными, используйте import инструкции из вызывающей программы. Инструкция import использует пространство имен, которое определяется для зависимости в файле манифеста.

Например, рассмотрим зависимость в следующем файле манифеста:

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

Импорт вызываемых файлов с помощью следующего кода:

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

...

Инструкция import также поддерживает синтаксис подстановочных символов и псевдонимы.

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

Пример внешнего проекта

В этом примере используйте ту же программу телепортации, что и предыдущий пример, но отделяйте вызывающую программу и вызываемые элементы в разных проектах.

  1. Создайте две папки на локальном диске, например Project_A и Project_B.

  2. Создайте проект в каждой Q# папке. Дополнительные сведения см. в руководстве по созданию Q# проекта.

  3. В Project_Aвызывающей программе скопируйте следующий код в файл манифеста, но измените путь для Project_B, если это необходимо.

    {
      "author": "Microsoft",
      "license": "MIT",
      "dependencies": {
        "MyTeleportLib": {
          "path": "/Project_B" 
          }
        }
      }    
    
  4. Скопируйте Project_Aследующий код в 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. Скопируйте Project_Bследующий код в 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
    

    Примечание.

    Вам не нужно экспортировать PrepareBellPair операцию, если программа в Project_A не вызывает её напрямую. Операция PrepareBellPair уже доступна операцией Teleport , так как PrepareBellPair находится в локальной области Project_B.

  6. Чтобы запустить программу, откройте /Project_A/Main.qsVS Code и нажмите кнопку "Выполнить".

Проекты и неявные пространства имен

В Q# проектах, если пространство имен в .qs программе не указано, компилятор использует имя файла в качестве пространства имен. Затем, при ссылке на вызываемую функцию из внешней зависимости, используйте следующий синтаксис <dependencyName>.<namespace>.<callable>. Однако если файл называется Main.qs, компилятор предполагает, что пространство имен и синтаксис вызова являются <dependencyName>.<callable>. Например: import MyTeleportLib.Teleport.

Так как у вас может быть несколько файлов проекта, необходимо учитывать правильный синтаксис при обращении к вызываемым файлам. Например, рассмотрим проект со следующей структурой файлов:

  • /src
    • Main.qs
    • MathFunctions.qs

Следующий код вызывает внешнюю зависимость:

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

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

Дополнительные сведения о поведении пространства имен см. в разделе "Пространства имен пользователей".