你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
Q# 程序的运行方式
Quantum 开发工具包的最大优势之一是其跨平台和开发环境的灵活性。 但是,这种灵活性也意味着,Q# 的新用户可能会对大量选项(请参阅安装指南)感到困惑或不知所措。 本页介绍运行 Q# 程序时所发生的情况,并比较用户运行程序的不同方式。
主要区别在于,可以采用以下方式运行 Q#:
- 作为独立应用程序运行,采用这种方式时,Q# 是所涉及的唯一一种语言,并且程序是直接调用的。 两种方式实际上属于以下类别:
- 命令行接口
- Q# Jupyter Notebook
- 与使用 Python 或 .NET 语言编写的额外主机程序(例如 C# 或 F#)一起运行,然后该主机程序将调用 Q# 程序,并且可以进一步处理返回的结果。
为了更好地理解这些过程及它们之间的区别,我们可以考虑使用 Q# 程序并对不同的运行方式进行比较。
基本 Q# 程序
基本的量子程序可能涉及准备处于 $\ket{0}$ and $\ket{1}$ 等量叠加状态的量子比特、测量叠加以及返回结果。 返回的结果随机处于这两种状态之一并具有相同概率。 事实上,此过程是量子随机数生成器快速入门的核心。
在 Q# 中,随机数生成将由以下代码执行:
use q = Qubit(); // allocates qubit for use (automatically in |0>)
H(q); // puts qubit in superposition of |0> and |1>
return MResetZ(q); // measures qubit, returns result (and resets it to |0> before deallocation)
但是,此代码无法单独由 Q# 运行。 若要运行,它需要构成操作的主体,然后在直接调用或通过其他操作调用时运行该操作。 因此,你可以编写以下形式的操作:
operation MeasureSuperposition() : Result {
use q = Qubit(); // allocates qubit for use (automatically in |0>)
H(q); // puts qubit in superposition of |0> and |1>
return MResetZ(q); // measures qubit, returns result (and resets it to |0> before deallocation)
}
你定义了 MeasureSuperposition 操作,该操作不接受输入并返回类型为 Result 的值。
除了操作之外,Q# 还允许将确定性计算封装到函数中。 除了表示所执行的计算的确定性保证之外,还需要将量子比特封装到操作而非函数中,操作和函数之间存在细微差别。 我们将其统称为可调用对象。
在 Q# 文件中定义的可调用对象
可调用对象是由 Q# 调用并运行的具体对象。
但是,它需要额外添加一些内容才能构成完整的 *.qsQ# 文件。
所有 Q# 类型和可调用对象(你定义的可调用对象和语言内部的可调用对象)都在命名空间中定义,命名空间分别提供了可供引用的全名。
例如,H 和 MResetZ 操作分别位于 Microsoft.Quantum.Instrinsic 和 Microsoft.Quantum.Measurement 命名空间(Q# 标准库的一部分)中。
因此,始终可以通过全名 Microsoft.Quantum.Intrinsic.H(<qubit>) 和 Microsoft.Quantum.Measurement.MResetZ(<qubit>) 调用它们,但一直执行此完整规范会导致代码非常杂乱。
相反,通过 open 语句,我们可以使用更简洁的简写来引用可调用对象,正如在上述操作主体中所做的那样。
因此,包含我们的操作的完整 Q# 文件将涉及定义我们自己的命名空间、为我们的操作所使用的可调用对象打开命名空间以及打开操作:
namespace Superposition {
open Microsoft.Quantum.Intrinsic; // for the H operation
open Microsoft.Quantum.Measurement; // for MResetZ
operation MeasureSuperposition() : Result {
use q = Qubit(); // allocates qubit for use (automatically in |0>)
H(q); // puts qubit in superposition of |0> and |1>
return MResetZ(q); // measures qubit, returns result (and resets it to |0> before deallocation)
}
}
注意
我们还可以在打开命名空间时为其指定别名。当两个命名空间中的可调用对象/类型名称相冲突时,这很有用。
例如,可以改为使用上面的 open Microsoft.Quantum.Instrinsic as NamespaceWithH;,然后通过 NamespaceWithH.H(<qubit>) 调用 H。
注意
唯一的例外是 Microsoft.Quantum.Core 命名空间,此命名空间始终会自动打开。
因此,Length 等可调用对象始终可以直接使用。
在目标计算机上运行
现在,我们已了解 Q# 程序的常规运行模型。
要运行的特定可调用对象有权访问同一个命名空间中定义的任何其他可调用对象和类型。
它还访问任意 Q# 库中的这些可调用项,但必须通过全名引用这些可调用项,或者通过使用上述 open 语句来引用。
可调用对象随后在 目标计算机 上运行。
此类目标计算机可以是实际的量子硬件,也可以是作为 QDK 的一部分提供的多个模拟器。
在这里,最有用的目标计算机是全态模拟器QuantumSimulator 的实例,该实例计算程序的行为,就像它是在无干扰量子计算机上运行的一样。
到目前为止,你了解了在运行特定的 Q# 可调用对象时将发生的情况。 无论是在独立应用程序中使用 Q# 还是与主机程序一起使用,此通用过程都大致相同,因此 QDK 具有灵活性。 因此,Quantum 开发工具包的不同调用方式之间的区别体现了调用 Q# 可调用对象的方式以及返回任何结果的方式。 更具体地说,主要区别包括:
- 指示要运行的 Q# 可调用对象
- 如何提供可能的可调用参数
- 指定要运行该可调用对象的目标计算机
- 如何返回任何结果
在下面的部分中,你将了解如何通过命令提示符使用 Q# 独立应用程序来实现这些操作, 然后继续了解使用 Python 和 C# 主机程序的情况。 我们将 Q# Jupyter Notebook 的独立应用程序留到最后介绍,因为与前三种运行方式不同,它的主要功能不以本地 Q# 文件为中心。
注意
虽然没有在这些示例中进行说明,但不同运行方式之间的一个共同点是:从 Q# 程序中输出的任何消息(例如通过 Message 或 DumpMachine 方法)通常始终会输出到相应的控制台。
通过命令提示符运行 Q#
这是开始编写 Q# 程序的最简单方法之一,因为我们完全无需担心单独的文件和另一种语言会造成混乱。 通过使用 Visual Studio Code 或带有 QDK 扩展的 Visual Studio,我们可以实现一个无缝的工作流,在该工作流中,我们仅运行单个 Q# 文件中的 Q# 可调用对象。
为此,你最终将通过在命令提示符下输入以下命令来运行程序
dotnet run
。
例如,最简单的工作流是:终端的目录位置与 Q# 文件相同,使用 VS Code 中的集成终端可以轻松地在编辑 Q# 文件的同时处理目录位置。
但是,dotnet run 命令接受许多选项,而且还可以通过向 --project <PATH> 提供 Q# 文件的位置从其他位置运行程序。
向 Q# 文件添加入口点
大多数 Q# 文件将包含多个可调用对象,因此,我们当然需要让编译器知道在提供 dotnet run 命令时要运行的可调用对象。
通过对 Q# 文件本身进行简单的更改即可实现此规范;需要直接在可调用对象之前使用 @EntryPoint() 添加一行。
完成上述更改后,文件将变为如下所示:
namespace Superposition {
open Microsoft.Quantum.Intrinsic; // for the H operation
open Microsoft.Quantum.Measurement; // for MResetZ
@EntryPoint()
operation MeasureSuperposition() : Result {
use q = Qubit(); // allocates qubit for use (automatically in |0>)
H(q); // puts qubit in superposition of |0> and |1>
return MResetZ(q); // measures qubit, returns result (and resets it to |0> before deallocation)
}
}
现在,通过命令提示符调用 dotnet run 会导致运行 MeasureSuperposition,并且返回值随后会直接输出到终端。
因此,你会看到输出了 One 或 Zero。
无论是否在下面定义了其他可调用对象,系统都只会运行 MeasureSuperposition。
此外,即使可调用对象的声明前面包含文档注释,也不会造成任何问题,可在文档注释上面放置 @EntryPoint() 属性。
可调用参数
到目前为止,本文仅考虑了没有输入的操作。 假设你想要执行类似的操作,但针对的是多个量子比特(量子比特数作为参数提供)执行。 可以按如下方式编写此类操作:
namespace MultiSuperposition {
open Microsoft.Quantum.Intrinsic; // for the H operation
open Microsoft.Quantum.Measurement; // for MResetZ
open Microsoft.Quantum.Canon; // for ApplyToEach
open Microsoft.Quantum.Arrays; // for ForEach
@EntryPoint()
operation MeasureSuperpositionArray(n : Int) : Result[] {
use qubits = Qubit[n]; // allocate a register of n qubits in |0>
ApplyToEach(H, qubits); // apply H to each qubit in the register
return ForEach(MResetZ, qubits); // perform MResetZ on each qubit, returns the resulting array
}
}
其中,返回值是测量结果的数组。
ApplyToEach 和 ForEach 分别位于 Microsoft.Quantum.Canon 和 Microsoft.Quantum.Arrays 命名空间中,它们分别需要另一个 open 语句。
如果将 @EntryPoint() 属性移至此新操作前面(请注意,一个文件中只能有一个这样的行),并尝试仅使用 dotnet run 来运行此操作,则会生成错误消息,指明需要哪个命令行选项,以及如何表示这些选项。
命令行的常规格式实际上是 dotnet run [options],并需在其中提供可调用参数。
在此案例中,参数 n 缺失,这表明我们需要提供选项 -n <n>。
若要针对 n=4 个量子比特运行 MeasureSuperpositionArray,需要运行以下命令:
dotnet run -n 4
生成的输出如下所示
[Zero,One,One,One]
当然,这可以扩展到多个参数。
注意
编译器会对 camelCase 中定义的参数名称稍做更改,以将其接受为 Q# 输入。
例如,在上面的示例中,如果使用名称 numQubits 而非 n,此输入在命令行中则将通过 --num-qubits 4 而非 -n 4 提供。
错误消息还会提供可使用的其他方案,包括如何更改目标计算机。
不同的目标计算机
到目前为止,由于操作的输出是对实际量子比特执行的操作的预期结果,因此很明显,命令行中的默认目标计算机是全状态量子模拟器 QuantumSimulator。
然而,可以使用选项 --simulator(或简写 -s)来指示可调用对象在特定的目标计算机上运行。
例如,可以在 ResourcesEstimator 上运行可调用对象:
dotnet run -n 4 -s ResourcesEstimator
那么打印输出将如下所示
Metric Sum
CNOT 0
QubitClifford 4
R 0
Measure 4
T 0
Depth 0
Width 4
BorrowedWidth 0
有关这些指标含义的详细信息,请参阅资源估算器:报告的指标。
命令行运行摘要
非 Q#dotnet run 选项
正如上文所简要提到的,使用 --project 选项时,dotnet run 命令还会接受与 Q# 可调用对象不相关的选项。
如果同时提供两种选项,则必须先提供特定于 dotnet 的选项并后跟分隔符 --,然后再提供特定于 Q# 的选项。
例如,如果为上述操作提供路径和量子比特数,则会通过 dotnet run --project <PATH> -- -n <n> 运行操作。
使用主机程序运行 Q#
准备好 Q# 文件之后,替代直接通过命令提示符调用操作或函数的方法是通过另一种经典语言使用主机程序。 具体来说,我们可以使用 Python 或 .NET 语言(例如 C# 或 F#,为了简单起见,我们在此处仅详细介绍 C#)来执行此调用。 若要启用互操作性,还需要进行其他一些设置。有关这些设置的详细信息,请参阅安装指南。
简而言之,现在的情况是,主机程序文件(例如,*.py 或 *.cs)与 Q# 文件位于相同的位置。
现在运行的是主机程序。 在运行时,它可以从 Q# 文件调用特定的 Q# 操作和函数。
互操作性的核心建立在 Q# 编译器之上,这使得主机程序可以访问并调用 Q# 文件的内容。
使用主机程序的一个主要优点是,可以使用主机语言来进一步处理 Q# 程序返回的传统数据。 这种处理可能包括一些高级数据处理(例如,无法在 Q# 内部完成的数据处理),然后根据这些结果调用其他 Q# 操作,或者像绘制 Q# 结果一样简单的数据处理。
此处显示了通用方案,我们将在下文讨论 Python 和 C# 的特定实现。 有关使用 F# 主机程序的示例,请参阅 .NET 互操作性示例。
注意
用于 Q# 应用程序的 @EntryPoint() 属性不能与主机程序一起使用。
如果主机调用的 Q# 文件中存在该属性,则会引发错误。
若要使用其他宿主程序,无需对 *.qsQ# 文件进行任何更改。
以下主机程序实现均使用同一个 Q# 文件:
namespace Superposition {
open Microsoft.Quantum.Intrinsic; // for H
open Microsoft.Quantum.Measurement; // for MResetZ
open Microsoft.Quantum.Canon; // for ApplyToEach
open Microsoft.Quantum.Arrays; // for ForEach
operation MeasureSuperposition() : Result {
use q = Qubit(); // allocates qubit for use (automatically in |0>)
H(q); // puts qubit in superposition of |0> and |1>
return MResetZ(q); // measures qubit, returns result (and resets it to |0> before deallocation)
}
operation MeasureSuperpositionArray(n : Int) : Result[] {
use qubits = Qubit[n];
ApplyToEach(H, qubits);
return ForEach(MResetZ, qubits);
}
}
选择相关主机语言对应的选项卡。
Python 主机程序的构造方式如下所示:
导入
qsharp模块,该模块将注册模块加载程序来实现 Q# 互操作性。 此导入允许 Q# 命名空间显示为 Python 模块,我们可以从中导入 Q# 可调用对象。 从技术上讲,导入的并不是 Q# 可调用对象本身,而是允许调用这些对象的 Python 存根。 这些存根的行为方式与 Python 类的对象相似。 可以针对这些对象使用方法来指定目标计算机,在运行程序时操作将发送到此目标计算机。导入将直接调用的 Q# 可调用对象。在本例中,它们是
MeasureSuperposition和MeasureSuperpositionArray。import qsharp from Superposition import MeasureSuperposition, MeasureSuperpositionArray导入
qsharp模块后,还可以直接从 Q# 库命名空间导入可调用对象。除了常规 Python 代码,你现在还可以在特定的目标计算机上运行这些可调用对象,并将其返回值分配给变量供进一步使用:
random_bit = MeasureSuperposition.simulate() print(random_bit)
诊断
与 Q# 独立笔记本一样,还可以使用 Python 笔记本中的 DumpMachine 和 DumpOperation 等诊断信息来了解 Q# 程序的工作方式,以及帮助诊断 Q# 程序中的问题和 bug。
namespace DumpOperation {
open Microsoft.Quantum.Diagnostics;
operation DumpPlusState() : Unit {
use q = Qubit();
within {
H(q);
} apply {
DumpMachine();
}
}
}
from DumpOperation import DumpPlusState
print(DumpPlusState.simulate())
调用 DumpMachine function 生成以下输出:
# wave function for qubits with ids (least to most significant): 0
∣0❭: 0.707107 + 0.000000 i == *********** [ 0.500000 ] --- [ 0.00000 rad ]
∣1❭: 0.707107 + 0.000000 i == *********** [ 0.500000 ] --- [ 0.00000 rad ]
使用 Q# 包还可以捕获这些诊断信息并将其作为 Python 对象进行操作:
with qsharp.capture_diagnostics() as diagnostics:
DumpPlusState.simulate()
print(diagnostics)
[{'diagnostic_kind': 'state-vector',
'div_id': 'dump-machine-div-7d3eac24-85c5-4080-b123-4a76cacaf58f',
'qubit_ids': [0],
'n_qubits': 1,
'amplitudes': [{'Real': 0.7071067811865476,
'Imaginary': 0.0,
'Magnitude': 0.7071067811865476,
'Phase': 0.0},
{'Real': 0.7071067811865476,
'Imaginary': 0.0,
'Magnitude': 0.7071067811865476,
'Phase': 0.0}]}]
使用原始 JSON 进行诊断可能不太方便,因此 capture_diagnostics 函数还支持使用 QuTiP 库将诊断信息转换为量子对象:
with qsharp.capture_diagnostics(as_qobj=True) as diagnostics:
DumpPlusState.simulate()
diagnostics[0]
Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket
Qobj data =
[[0.707]
[0.707]]
若要详细了解 Q# 和 Quantum 开发工具包提供的诊断功能,请参阅测试和调试。
指定目标计算机
通过直接在导入的操作对象上调用 Python 方法,可在特定的目标计算机上运行 Q# 操作。 因此,无需为运行目标(例如模拟器)创建对象。 相反,请调用以下方法之一运行导入 Q# 的操作:
.simulate(<args>)使用完整状态模拟器模拟理想量子计算机的运算。 (.simulate()的 API 参考)。.simulate_sparse(<args>)使用稀疏模拟器模拟理想量子计算机的操作。 (.simulate_sparse()的 API 参考)。.estimate_resources(<args>)使用 资源估算器计算程序所需的各种量子资源。 (.estimate_resources()的 API 参考)。.toffoli_simulate(<args>)使用 Toffoli 模拟器为受限的量子程序类提供更有效的模拟方法。 (.toffoli_simulate()的 API 参考)。.simulate_noise(<args>)使用噪声模拟器在噪声的影响下模拟开放量子系统中的运算。 可以通过调用qsharp.experimental.enable_noisy_simulation()来启用噪声模拟器。
有关本地目标计算机的信息,请参阅 Quantum 模拟器。
在 Q# 中将参数传递给可调用对象
应以关键字参数的形式提供 Q# 可调用对象的参数,其中,关键字是 Q# 可调用对象定义中的参数名称。
也就是说,MeasureSuperpositionArray.simulate(n=4) 有效,而 MeasureSuperpositionArray.simulate(4) 将会引发错误。
因此,Python 主机程序
import qsharp
from Superposition import MeasureSuperposition, MeasureSuperpositionArray
single_qubit_result = MeasureSuperposition.simulate()
single_qubit_resources = MeasureSuperposition.estimate_resources()
multi_qubit_result = MeasureSuperpositionArray.simulate(n=4)
multi_qubit_resources = MeasureSuperpositionArray.estimate_resources(n=4)
print('Single qubit:\n' + str(single_qubit_result))
print(single_qubit_resources)
print('\nMultiple qubits:\n' + str(multi_qubit_result))
print(multi_qubit_resources)
生成如下输出:
Single qubit:
1
{'CNOT': 0, 'QubitClifford': 1, 'R': 0, 'Measure': 1, 'T': 0, 'Depth': 0, 'Width': 1, 'BorrowedWidth': 0}
Multiple qubits:
[0, 1, 1, 1]
{'CNOT': 0, 'QubitClifford': 4, 'R': 0, 'Measure': 4, 'T': 0, 'Depth': 0, 'Width': 4, 'BorrowedWidth': 0}
还可以采用类似的方式传递数组。 可以在可逆的逻辑综合示例中查看示例。
不能将量子比特作为经典代码中的参数传递。 与 Q# 类型相关的任何逻辑,例如 Qubit,应该位于你的 Q# 代码中。 如果希望你的 Python 代码指定量子比特数,可以向你的 nQubits : Int 操作添加类似 Q# 等参数。 Python 代码可以将量子比特数作为整数传递,Q# 代码随后可以分配适当数量的量子比特数组。
对于 Pauli 和 Result 类型,实际定义了 Python 枚举,这样一来,使你可以按需直接传递这些值。 请参阅 qsharp.Pauli 和 qsharp.Result。
使用其他项目或包中的 Q# 代码
默认情况下,import qsharp 命令会加载当前文件夹中的所有 .qs 文件,并使这些文件中的 Q# 操作和函数可供在 Python 脚本中使用。
若要从其他文件夹加载 Q# 代码,可以使用 qsharp.projects API 为 Q# 项目(即引用 Microsoft.Quantum.Sdk 的项目)添加对 .csproj 文件的引用。
此命令将在包含 .csproj 及其子文件夹的文件夹中编译任何 .qs 文件。 此命令还会以递归方式加载该 .csproj 文件中通过 PackageReference 引用的任何包含或通过 ProjectReference 引用的 Q# 项目。
例如,以下 Python 代码将导入外部项目,引用其相对于当前文件夹的路径,并调用其 Q# 操作之一:
import qsharp
qsharp.projects.add("../qrng/Qrng.csproj")
from Qrng import SampleQuantumRandomNumberGenerator
print(f"Qrng result: {SampleQuantumRandomNumberGenerator.simulate()}")
此代码将生成输出,如下所示:
Adding reference to project: ../qrng/Qrng.csproj
Qrng result: 0
若要加载包含 Q# 代码的外部包,请使用 qsharp.packages API。
如果当前文件夹中的 Q# 代码依赖于外部项目或包,则在运行 import qsharp 时可能会看到错误,因为尚未加载依赖项。
若要在运行 import qsharp 命令期间加载所需的外部包或 Q# 项目,请确保包含 Python 脚本的文件夹同时包含引用 Microsoft.Quantum.Sdk 的 .csproj 文件。 在该 .csproj 文件中,将属性 <IQSharpLoadAutomatically>true</IQSharpLoadAutomatically> 添加到 <PropertyGroup>。 此更改将指示 IQ# 在运行 import qsharp 命令期间以递归方式加载在该 .csproj 文件中找到任何 ProjectReference 或 PackageReference 项。
例如,此处显示了一个简单的 .csproj 文件,该文件将导致 IQ# 自动加载 Microsoft.Quantum.Chemistry 包:
<Project Sdk="Microsoft.Quantum.Sdk/0.17.2105143879">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.1</TargetFramework>
<IQSharpLoadAutomatically>true</IQSharpLoadAutomatically>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Chemistry" Version="0.17.2105143879" />
</ItemGroup>
</Project>
注意
目前,Python 主机需要此自定义 <IQSharpLoadAutomatically> 属性,但在将来,这可能会成为与 Python 脚本位于同一个文件夹中的 .csproj 文件的默认行为。
注意
目前,Python 主机会忽略 .csproj 中的 <QsharpCompile> 设置,并且会加载并编译 .csproj 的文件夹中的所有 .qs 文件(包括子文件夹)。 将来会改进对 .csproj 设置的支持(有关详细信息,请参阅 iqsharp#277)。
Q# Jupyter Notebook
Q# Jupyter Notebook 使用 IQ# 内核,这使你可以在单个笔记本中定义、编译并运行 Q# 可调用对象,所有说明、注释及其他内容也保存在该笔记本中。
这意味着,虽然我们可以导入并使用 *.qsQ# 文件的内容,但这种运行模型不需要这些文件。
此处详细介绍了如何运行上面定义的 Q# 操作, 但如果要查看与使用 Q# Jupyter Notebook 相关的更广泛的介绍,请参阅设置 Q# 独立环境。
定义操作
在 Q# Jupyter Notebook 中,可以像在 Q# 文件的命名空间中一样输入 Q# 代码。
因此,可以使用 open 语句为各自的命名空间启用对 Q# 标准库中的可调用对象的访问。
使用此类语句运行一个单元时,这些命名空间中的定义在整个工作区都可用。
注意
Microsoft.Quantum.Intrinsic 和 Microsoft.Quantum.Canon 中的可调用对象(例如,H 和 ApplyToEach)会自动提供给 Q# Jupyter Notebook 中的单元内定义的操作。
但是,对于从外部 Q# 源文件引入的代码(Q# 和 Jupyter Notebook 简介中介绍了引入过程),情况并非如此。
同样,定义操作时只需编写 Q# 代码并运行单元。
然后,输出会列出这些操作,随后可以从以后的单元中调用这些操作。
目标计算机
在特定的目标计算机上运行操作的功能通过 IQ# magic 命令提供。
例如,%simulate 使用 QuantumSimulator,而 %estimate 使用 ResourcesEstimator:
在 Q# 中将参数传递给可调用对象
若要将输入传递到 Q# 操作,可以将参数作为 key=value 对传递到所运行的 magic 命令。
因此,若要使用四个量子比特运行 MeasureSuperpositionArray,我们可以运行 %simulate MeasureSuperpositionArray n=4:
可以采用与 %estimate 及其他 run 命令类似的方式使用此模式。
注意
无法以类似方式通过运行命令(如 或 ) %simulate%estimate 传递可调用项。
使用其他项目或包中的 Q# 代码
默认情况下,Q# Jupyter Notebook 会加载当前文件夹中的所有 .qs 文件,并使这些文件中的 Q# 操作和函数可供在笔记本中使用。 %who magic 命令会列出当前可用的所有 Q# 操作和函数。
若要从其他文件夹加载 Q# 代码,可以使用 %project magic 命令 为 Q# 项目(即引用 Microsoft.Quantum.Sdk 的项目)添加对 .csproj 文件的引用。 此命令将在包含 .csproj(及其=子文件夹)的文件夹中编译任何 .qs 文件。 此命令还会以递归方式加载该 .csproj 文件中通过 PackageReference 引用的任何包含或通过 ProjectReference 引用的 Q# 项目。
例如,以下单元模拟外部项目中的 Q# 操作,其中相对于当前文件夹引用项目路径:
若要加载包含 Q# 代码的外部包,请使用 %package magic 命令。
加载包还会使任何自定义的 magic 命令或属于包一部分的任何程序集中包含的显示编码器变为可用。
若要在笔记本初始化时加载外部包或 Q# 项目,请确保笔记本文件夹包含引用 Microsoft.Quantum.Sdk 的 .csproj 文件。 在该 .csproj 文件中,将属性 <IQSharpLoadAutomatically>true</IQSharpLoadAutomatically> 添加到 <PropertyGroup>。 该属性将指示 IQ# 在笔记本加载时以递归方式加载在该 .csproj 文件中找到任何 ProjectReference 或 PackageReference 项。
例如,此处显示了一个简单的 .csproj 文件,该文件将导致 IQ# 自动加载 Microsoft.Quantum.Chemistry 包:
<Project Sdk="Microsoft.Quantum.Sdk/0.17.2105143879">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.1</TargetFramework>
<IQSharpLoadAutomatically>true</IQSharpLoadAutomatically>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Chemistry" Version="0.17.2105143879" />
</ItemGroup>
</Project>
注意
目前,Q# Jupyter Notebook 主机需要此自定义 <IQSharpLoadAutomatically> 属性,但在将来,这可能会成为与笔记本文件位于同一个文件夹中的 .csproj 文件的默认行为。
注意
目前,Q# Jupyter Notebook 主机会忽略 .csproj 中的 <QsharpCompile> 设置,并且会加载并编译 .csproj 的文件夹中的所有 .qs 文件(包括子文件夹)。 将来会改进对 .csproj 设置的支持(有关详细信息,请参阅 iqsharp#277)。