你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
本文介绍如何创建、管理和共享 Q# 项目。 Q#项目是一个文件夹结构,其中包含多个Q#文件,可以访问彼此的作和函数。 项目有助于在逻辑上组织源代码。 还可以将项目用作可从外部源访问的自定义库。
先决条件
- Azure 订阅中的 Azure Quantum 工作区。 若要创建工作区,请参阅创建 Azure Quantum 工作区。
- 安装了 Azure Quantum Development Kit 和 Python 扩展的 Visual Studio Code (VS Code)。
- 发布外部项目到公共 GitHub 存储库时,需拥有一个 GitHub 帐户。
若要运行 Python 程序,还需要:
- 安装了 Python 和 Pip 的 Python 环境。
- Azure Quantum
qsharp和azure-quantum包。
项目工作原理Q#
Q#项目包含一个名为qsharp.json的清单文件和一个或多个.qs文件,这些文件位于指定的Q#文件夹结构中。 可以在 VS Code 中手动或直接创建 Q# 项目。
在 VS Code 中打开 .qs 文件时,编译器会在周围的文件夹层级中搜索清单文件,并确定项目的范围。 如果未找到清单文件,编译器将在单个文件模式下运行。
在 Jupyter Notebook 或 Python 文件中设置 project_root 时,编译器将在文件夹中查找清单文件 project_root 。
外部 Q# 项目是驻留在另一个目录或公共 GitHub 存储库中的标准 Q# 项目,充当自定义库。 外部项目使用 export 语句定义外部程序可访问的函数和作。 程序将外部项目定义为其清单文件中的依赖项,并使用 import 语句访问外部项目中的项,例如作、函数、结构和命名空间。 有关详细信息,请参阅 将项目用作外部依赖项。
定义Q#项目
Q#项目由存在清单文件(命名qsharp.json)和src文件夹定义,这两者都必须位于项目的根文件夹中。 该 src 文件夹包含 Q# 源文件。 对于 Q# 程序和外部项目, Q# 编译器会自动检测项目文件夹。 对于 Python 程序和 Jupyter Notebook 文件,必须使用一个调用语句来指定项目文件夹。 但是,项目的文件夹结构 Q# 对于所有类型的程序都是相同的。
定义项目文件夹(Q# 程序)
在 VS Code 中打开 .qs 文件时, Q# 编译器会在文件夹结构中向上搜索清单文件。 如果编译器找到清单文件,编译器将包括目录中的所有 Q# 文件 /src 及其所有子目录。 每个文件中定义的项可供项目中的所有其他文件使用。
例如,请考虑以下文件夹结构:
-
Teleportation_project
- qsharp.json
-
src
- Main.qs
-
TeleportOperations
- TeleportLib.qs
-
PrepareState
- PrepareStateLib.qs
打开文件 /src/TeleportOperation/PrepareState/PrepareStateLib.qs 时,Q# 编译器执行以下操作:
- 检查
/src/TeleportOperation/PrepareState/的qsharp.json。 - 检查
/src/TeleportOperation以检查qsharp.json。 - 检查
/src的qsharp.json。 - 检查
/*是否有qsharp.json。 -
/根据清单文件的设置,建立为项目的根目录,并在项目根目录下包括所有.qs文件。
创建清单文件
清单文件是一个 JSON qsharp.json 文件,可选择性地包括 作者、 许可证和 lints 字段。 最小可行清单文件是字符串 {}。 在 VS Code 中创建 Q# 项目时,会为你创建一个最小的清单文件。
{}
清单文件示例
以下示例显示如何通过清单文件来定义你的项目 Q# 的范围。
在此示例中, 作者 是唯一指定的字段,因此此目录中的所有
.qs文件及其子目录都包含在 Q# 项目中。{ "author":"Microsoft", "license": "MIT" }在一个Q#项目中,还可以使用清单文件来微调 VS Code Q# Linter 设置。 默认情况下,三个 Linter 规则为:
needlessParens:默认 =allowdivisionByZero:默认 =warnredundantSemicolons:默认 =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# 下。 在 VS Code 中创建 Q# 项目时,/src将自动创建该文件夹。清单文件应与
src文件夹位于同一级别。 在 VS Code 中创建 Q# 项目时,会自动创建最小文件。使用
import语句引用项目中其他文件中的操作和函数。import MyMathLib.*; //imports all the callables in the MyMathLib namespace ... Multiply(x,y);或者,使用命名空间单独引用它们。
MyMathLib.Multiply(x,y);
仅适用于 Q# 项目
- 您只能在项目中的一个
.qs文件中定义入口点操作,该操作是默认的Main()操作。 - 必须将具有入口点定义的文件放在
.qs清单文件下面的项目目录级别。 - 项目中所有的操作和函数,Q# 显示中的内容会被缓存到
.qs,并且在 VS Code 的预测文本中展示。 - 如果尚未导入所选作或函数的命名空间,则 VS Code 会自动添加必要的
import语句。
如何创建 Q# 项目
若要创建 Q# 项目,请执行以下步骤:
在 VS Code 文件资源管理器中,转到要用作项目的根文件夹的文件夹 Q# 。
打开 “视图 ”菜单,然后选择 “命令面板”。
输入 QDK:创建 Q# 项目 ,然后按 Enter。 VS Code 在文件夹中创建最小清单文件,并添加包含
/srcMain.qs模板文件的文件夹。编辑项目的Manifest文件。 请参阅清单文件示例。
将您的Q#源文件添加并组织在
/src文件夹下。如果要从 Python 程序或 Jupyter Notebook 访问Q#项目,请使用 设置
qsharp.init。 假设此示例程序位于/src项目的 Q# 文件夹中:qsharp.init(project_root = '../Teleportation_project')如果仅在 Q# VS Code 中使用文件,则编译器在打开 Q# 文件时搜索清单文件,确定项目的根文件夹,然后扫描子文件夹查找
.qs文件。
注意
还可以手动创建清单文件和 /src 文件夹。
示例项目
此量子传送程序是在 VS Code 中的本地模拟器上运行的项目示例 Q# 。 若要在 Azure Quantum 硬件或第三方模拟器上运行程序,请参阅程序和 VS Code 入门Q#,了解编译程序并连接到 Azure Quantum 工作区的步骤。
此示例具有以下目录结构:
-
Teleportation_project
- qsharp.json
-
src
- Main.qs
-
TeleportOperations
- TeleportLib.qs
-
PrepareState
- PrepareStateLib.qs
清单文件包含 作者 和 许可证 字段:
{
"author":"Microsoft",
"license":"MIT"
}
Q# 源文件
名为Main.qs的主文件包含入口点,并引用TeleportLib.qs中的TeleportOperations.TeleportLib命名空间。
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 并从 PrepareStateLib.qs 文件调用 PrepareBellPair 操作。
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,则将 文件 属性添加到外部项目的清单文件中。
- 向外部项目添加
export语句。 - 向调用项目添加
import语句。
配置Manifest文件
外部 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 存储库,则必须将 文件 属性添加到外部项目的清单文件中,包括项目中使用的所有文件。
{
"author": "Microsoft",
"license": "MIT",
"files": [ "src/MyMathFunctions.qs", "src/Strings/MyStringFunctions.qs" ]
}
文件属性对于通过"path"(即基于本地 filepath 的导入)导入的外部项目是可选的。
文件属性仅适用于发布到 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;
注意
当前使用的 open 语句 Q#(用于引用库和命名空间)仍受支持,但最终将弃用。 同时,可以选择更新当前文件以使用 import 语句。 例如,可以使用 open Std.Diagnostics; 替换 import Std.Diagnostics.*;。
示例外部项目
对于此示例,你将使用与前面的示例相同的转接程序,但将呼叫程序和可调用者分开到不同的项目中。
在本地驱动器上创建两个文件夹,例如“Project_A”和“Project_B”。
在 Project_A 中,调用程序将以下代码复制到清单文件中,根据需要编辑Project_B的路径
{ "author": "Microsoft", "license": "MIT", "dependencies": { "MyTeleportLib": { "path": "/Project_B" } } }在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); } }在 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程序中调用。 由于它位于Project_B的本地范围内,Teleport操作已可访问该元素。若要运行程序,请在 VS Code 中打开
/Project_A/Main.qs并选择 “运行”。
项目和隐式命名空间
在 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
有关命名空间行为的详细信息,请参阅 用户命名空间。