你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
如何使用 Q# 项目
使用 AzureQuantum Development Kit,可以定义Q#项目,这些项目是具有多个Q#文件的文件夹结构,这些文件可以访问彼此的操作和函数。 项目有助于在逻辑上组织源代码。 还可以将项目用作外部依赖项或可从外部源访问的自定义库。
项目 Q# 包含一个名为 Q# qsharp.json的清单文件,以及指定文件夹结构中的一个或多个 *.qs 文件。 当用户在 VS Code 中打开 *.qs 文件或设置 project_root
Jupyter Notebook 或 Python 文件中时,编译器会在周围文件夹层次结构中搜索清单文件并确定项目的范围。 如果未找到清单文件,编译器将在单个文件模式下运行。 Q#可以在 VS Code 中手动或直接创建项目。
外部 Q# 项目是驻留在另一个目录或公共 GitHub 存储库中的标准 Q# 项目,并使用 export
语句定义外部程序可以访问哪些函数和操作。 程序将外部项目定义为其清单文件中的依赖项,并使用 import
语句访问外部项目中的项(操作、函数、结构和命名空间)。 有关详细信息,请参阅 将项目用作外部依赖项。
先决条件
- Azure 订阅中的 Azure Quantum 工作区。 若要创建工作区,请参阅创建 Azure Quantum 工作区。
- 安装了 Azure Quantum Development Kit 和 Python 扩展的 Visual Studio Code。
- 如果计划将外部项目发布到公共 GitHub 存储库,则为 GitHub 帐户。
若要运行 Python 程序,还需要:
- 安装了 Python 和 Pip 的 Python 环境。
- Azure Quantum
qsharp
和azure-quantum
包。
Q#定义项目
Q#项目由存在清单文件(名为qsharp.json)和 src 文件夹(其中包含Q#源文件)定义,这两个文件都必须位于项目的根文件夹中。 对于 Q# 程序和外部项目, Q# 编译器会自动检测项目文件夹。 对于 Python 程序和 Jupyter Notebook,必须使用调用指定 Q# 项目文件夹 qsharp.init
。 但是,对于所有类型的程序,项目的文件夹结构 Q# 保持不变。
定义项目文件夹(Q# 程序)
在 VS Code 中打开 *.qs 文件时, Q# 编译器会在文件夹结构中向上搜索清单文件。 如果找到清单文件,编译器随后将包括 /src 目录或其任何子目录中的所有 Q# 文件。 每个文件的项都可用于项目中的所有其他文件。
例如,给定此文件夹结构:
- 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 文件。
创建清单文件
清单文件是一 个名为qsharp.json的简单.json 文件,可以选择包括 作者、 许可证和 lints 字段。 最小可行清单文件是字符串 {}
。 在 VS Code 中创建 Q# 项目时,会为你创建一个最小的清单文件。
{}
清单文件示例
下面是清单文件如何定义项目范围的 Q# 一些示例。
在此示例中, 作者 是唯一指定的字段,因此此目录中的所有 *.qs 文件及其所有子目录都包含在 Q# 项目中。
{ "author":"Microsoft", "license": "MIT" }
Q#在项目中,还可以使用清单文件微调 VS Code Q# 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#根文件夹下。 在 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 文件 Q# 可以定义入口点,由单个
Main()
操作定义。 - 具有入口点定义的 *.qs 文件可以位于清单文件下方的任何级别。
- 从 *.qs 文件缓存的任何操作或函数在 Q# 项目中的任意位置都以 VS Code 中的预测文本形式显示。
- 如果尚未导入所选操作或函数的命名空间,VS Code 会自动添加必要的
import
语句。
创建 Q# 项目的步骤
这些步骤适用于所有 Q# 项目。
在 VS Code 文件资源管理器中,右键单击要用于项目根文件夹的文件夹Q#,然后选择“创建Q#项目”,或打开该文件夹,然后选择“查看>命令面板>Q#:创建Q#项目...”。
VS Code 在文件夹中创建最小清单文件,并添加包含
/src
Main.qs
模板文件的文件夹。根据需要编辑清单文件。 请参阅 清单文件示例。
在文件夹下
/src
添加和组织Q#源文件。如果要从 Python 程序或 Jupyter Notebook 访问Q#项目,请使用
qsharp.init
设置根文件夹路径。 此示例假定程序位于项目的 /src 文件夹中 Q# :qsharp.init(project_root = '../Teleportation_project')
如果只 Q# 使用 VS Code 中的文件,则在打开 Q# 文件时,编译器将搜索清单文件,确定项目的根文件夹,然后扫描子文件夹以获取 *.qs 文件。
注意
还可以在步骤 2 中手动创建清单文件和 /src
文件夹。
示例项目
此量子传送程序是基于前面显示的单个文件夹结构的项目示例 Q# ,并在 VS Code 中的本地模拟器上运行。 若要在 Azure Quantum 硬件或第三方模拟器上运行程序,请参阅程序和 VSCode 入门Q#,了解编译程序并连接到 Azure 工作区的步骤。
此示例使用此目录结构:
- 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 文件包含用于创建 Bell 对的标准可重用操作。
operation PrepareBellPair(left : Qubit, right : Qubit) : Unit is Adj + Ctl {
H(left);
CNOT(left, right);
}
运行程序
选择运行程序的环境的选项卡。
若要运行此程序,请在 VS Code 中打开 Main.qs 文件,然后选择“ 运行”。
将项目配置为 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 存储库,则必须将文件属性添加到外部项目的清单文件中,包括项目中使用的所有文件。
{
"author": "Microsoft",
"license": "MIT",
"files": [ "src/MyMathFunctions.qs", "src/Strings/MyStringFunctions.qs" ]
}
对于要通过 "path"
(即基于本地 filepath 的导入)导入的外部项目,“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;
注意
当前使用的 open
语句 Q#(用于引用库和命名空间)仍受支持,但最终将弃用。 同时,可以选择更新当前文件以使用 import
语句。 例如,可以使用 open Microsoft.Quantum.Diagnostics;
替换 import Microsoft.Quantum.Diagnostics.*;
。
另请注意,将 import
语句与标准 Q# 库一起使用时,可以将根命名空间缩短为 Std
。 例如,import Microsoft.Quantum.Diagnostics.*;
可以写为 import Std.Diagnostics.*;
。
示例外部项目
对于此示例,你将使用与前面的示例相同的转接程序,但将呼叫程序和可调用者分开到不同的项目中。
在本地驱动器上创建两个文件夹,例如“Project_A”和“Project_B”。
Q#按照步骤中的步骤创建项目,在每个文件夹中创建项目Q#。
在 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>。<命名空间>。<可>调用。 但是,如果文件名为“Main.qs”,则编译器假定命名空间,调用语法为 <dependencyName>。<可>调用,如上例 import MyTeleportLib.Teleport
所示。
由于有多个项目文件并不常见,因此在引用可调用项时需要考虑正确的语法。 例如,在具有以下文件结构的项目中
- src/
- Main.qs
- MathFunctions.qs
对外部依赖项的调用将是
import MyTeleportLib.MyFunction; // "Main" namespace is implied
import MyTeleportLib.MathFunctions.MyFunction; // "Math" namespace must be explicit
有关命名空间行为的详细信息,请参阅 用户命名空间。