你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

量子内存管理

程序总是以无量子比特开始,这意味着 Qubit 类型的值不能作为入口点参数传递。 这种限制是有意为之,因为 Q# 的目的是表达和推理整个程序。 程序会在运行时分配和释放量子比特或量子内存。 在这方面,Q# 将量子计算机建模为一个量子比特堆。

不支持量子内存的单独分配和释放语句,Q# 支持块语句形式的量子内存分配,其中只能在该块语句的范围内访问内存。 当分配量子比特在当前范围的持续时间时,可以隐式定义语句块,如有关 useborrow 语句的部分中所详述。 尝试在语句终止后访问分配的量子比特会导致运行时异常。

Q# 有两个语句(useborrow)来实例化量子比特值、数组或其任意组合。 只能在运算中使用这些语句。 它们收集实例化的量子比特值,将其绑定到语句中指定的变量,然后运行一个语句块。 在块的末尾,绑定的变量超出范围且不再定义。

Q# 区分干净量子比特和脏量子比特之间的分配。 干净量子比特是未纠缠的,并且不会由计算的另一部分使用。 脏量子比特是状态未知、甚至可以与量子处理器内存的其他部分纠缠在一起的量子比特。

Use 语句

干净量子比特由 use 语句分配。

  • 该语句由关键字 use 后跟一个绑定以及一个可选语句块组成。
  • 如果存在语句块,则量子比特仅在该块中可用。 否则,量子比特在当前范围内都可用。
  • 绑定遵循与 let 语句相同的模式:单个符号或符号元组,后跟等号 =,以及单个元组或匹配的初始值设定项元组。

初始值设定项可用于单个量子比特(表示为 Qubit())或量子比特数组 Qubit[n],其中 nInt 表达式。 例如,

use qubit = Qubit();
// ...

use (aux, register) = (Qubit(), Qubit[5]);
// ...

use qubit = Qubit() {
    // ...
}

use (aux, register) = (Qubit(), Qubit[5]) {
    // ...
}

量子比特在分配时保证处于 |0⟩ 状态。 它们在范围的末尾发布,并在发布时必须处于 |0⟩ 状态。 此要求不是编译器强制执行的,因为这将需要符号评估,其成本将很快变得高昂。 在模拟器上运行时,可以在运行时强制执行该要求。 在量子处理器上,要求不能在运行时强制执行;未测量的量子比特可以通过幺正变换重置为 |0⟩。 否则会导致不正确的行为。

use 语句从量子处理器的空闲量子比特堆中分配量子比特,并在绑定量子比特的范围结束之前将它们返回到堆中。

Borrow 语句

borrow 语句授予对已分配但当前未使用的量子比特的访问权限。 这些量子比特可以处于任意状态,并且当 borrow 语句终止时,需要再次处于同一状态。 某些量子算法可以使用量子比特,而无需依赖于其确切状态,并且不要求它们与系统的其余部分不纠缠。 也就是说,它们暂时需要额外的量子比特,但可以确保这些量子比特准确地返回到它们的原始状态,而与原状态相互独立。

如果在子例程中存在正在使用但未触及的量子比特,则可以借用这些量子比特供此类算法使用,而无需分配额外的量子内存。 借用取代分配可以显著降低算法的整体量子内存需求,并且是典型时空权衡的量子示例。

borrow 语句遵循与 use 语句 的上述相同模式,并提供相同的初始值设定项。 例如,

borrow qubit = Qubit();
// ...

borrow (aux, register) = (Qubit(), Qubit[5]);
// ...

borrow qubit = Qubit() {
    // ...
}

borrow (aux, register) = (Qubit(), Qubit[5]) {
    // ...
}

借用的量子比特处于未知状态,并在语句块末尾超出范围。 借用者承诺将量子比特保持在它们被借用时的相同状态,即在语句块开头和结尾的状态应该是相同的。

borrow 语句检索在使用中的量子比特,保证这些量子比特从绑定到最后一次使用期间不会被程序使用。 如果没有足够的量子比特可供借用,则会像 use 语句一样从堆中分配量子比特和将其返回到堆。

注意

脏量子比特的已知用例包括需要很少量子比特的多控制 CNOT 门的实现和增量器的实现。 这篇关于量子比特因素分解的论文提供了使用被借用的量子比特的算法的示例。