Quake 方言

Quake 方言

总体介绍

量子电路模型是应用最广泛的量子计算模型。它为表述量子算法提供了便利工具,也为量子计算机的物理构建提供了架构。

量子电路将计算表示为一个应用于量子数据的量子算子序列。在我们的场景中,量子数据是一组量子比特。物理上,一个量子比特是仅有两个可区分状态的对象,即它是一个二态量子力学系统,如自旋-1/2粒子。

概念上,量子算子是可能修改量子比特子集状态的效应。最常见的情况是,这种效应是幺正演化------此时,我们称该算子是幺正的。算子作用的目标量子比特数量是其固有属性。

量子指令是将量子算子应用于特定量子比特子集的具体体现。量子比特的数量必须等于(或大于)算子固有的目标量子比特数量。如果更大,额外的量子比特被视为控制比特。

动机

Quake 值模型背后的主要动机是,为了优化目的直接暴露量子与经典数据的依赖关系,即表示量子计算中的数据流。与 Quake 的内存模型(使用内存语义,量子算子作为对量子比特引用的副作用)不同,值模型使用值语义,即量子算子消费并产生值。然而,这些值并非真正的 SSA 值,因为操作仍然对值本身有副作用且值不能被复制。

我们来看一个例子以澄清两种模型之间的区别。以下是某个玩具量子计算的 Quake 实现:

mlir

复制代码
func.func foo(%veq : !quake.veq<2>) {
    // 从向量中提取每个量子比特的样板代码
    %c0 = arith.constant 0 : index
    %c1 = arith.constant 1 : index
    %q0 = quake.extract_ref %veq[%c0] : (!quake.veq<2>, index) -> !quake.ref
    %q1 = quake.extract_ref %veq[%c1] : (!quake.veq<2>, index) -> !quake.ref

    // 我们向这些提取的量子比特应用一些算子
    // ... 一系列使用 %q0 和 %q1 的算子 ...
    quake.h %q0 : (!quake.ref) -> ()

    // 我们决定测量该向量
    %result = quake.mz %veq : (!quake.veq<2>) -> cc.stdvec<i1>

    // 然后向 %q0 应用另一个 Hadamard
    quake.h %q0 : (!quake.ref) -> ()
    // ...
}

现在假设我们想通过移除相邻的伴随算子对来优化此代码,例如,如果在同一个量子比特上连续出现一对 Hadamard 操作------图示如下:

复制代码
    ┌───┐ ┌───┐         ┌───┐
   ─┤ H ├─┤ H ├─  =  ───┤ I ├───  =  ─────────────
    └───┘ └───┘         └───┘

其中 I 是恒等算子。注意,对 Quake 的这种优化的简单实现会优化掉应用于 %q0 的两个 quake.h 算子。这样的实现忽略了测量正被应用于包含 %q0 的向量 %veq 这一事实。

当然,为 Quake 正确实现这种优化是可能的。但这样的实现会很容易出错且需要复杂的分析。因此,Quake 具有重载的门。

在值模型中,算子消费值并返回新值:

mlir

复制代码
%q0_1 = quake.op %q0_0 : (!quake.wire) -> !quake.wire

我们可以将内存表示与值表示之间的差异可视化为:

复制代码
            内存表示                                  值表示

        ┌──┐ ┌──┐     ┌──┐                  ┌──┐ %q0_1 ┌──┐     ┌──┐
   %q0 ─┤  ├─┤  ├─···─┤  ├─ %q0  对比  %q0_0 ─┤  ├───────┤  ├─···─┤  ├─ %q0_Z
        └──┘ └──┘     └──┘                  └──┘       └──┘     └──┘

如果我们再次查看实现,会注意到简单优化的问题在于 Hadamard 算子通过相同的值 %q0 隐式连接。在值形式中,所有门都通过不同的值显式连接,这消除了通过隐式副作用进行进一步分析的需要。以下是值形式的实现。

mlir

复制代码
func.func @foo(%array : !quake.qvec<2>) {
    // 提取每个量子比特的样板代码
    %c0 = arith.constant 0 : index
    %c1 = arith.constant 1 : index
    %r0 = quake.extract_ref %array[%c0] : (!quake.qvec<2>, index) -> !quake.qref
    %r1 = quake.extract_ref %array[%c1] : (!quake.qvec<2>, index) -> !quake.qref

    // 解包量子引用以暴露连线
    %q0 = quake.unwrap %r0 : (!quake.qref) -> !quake.wire
    %q1 = quake.unwrap %r1 : (!quake.qref) -> !quake.wire

    // 应用各种算子
    %q0_M = quake.h %q0_L : (!quake.wire) -> !quake.wire

    // 将连线重新包装到其原始源
    quake.wrap %q0_M to %r0 : !quake.wire, !quake.qref
    quake.wrap %q1_X to %r1 : !quake.wire, !quake.qref

    // 测量整个量子引用向量
    %result = quake.mz %array : (!quake.qvec<2>) -> !cc.stdvec<i1>

    // 再次解包量子比特 0 的连线
    %q0_P = quake.unwrap %r0 : (!quake.qref) -> !quake.wire
    ...
    %q0_Z = quake.h %q0_Y : (!quake.wire) -> !quake.wire
    // 将连线重新包装回原始引用
    quake.wrap %q0_Z to %r0 : !quake.wire, !quake.qref
    return
}

在这段代码中,我们可以更直接地看出这两个 Hadamard 算子不能相互抵消。一种推理方式如下:在值形式中,我们需要遵循值链来了解量子比特算子被应用于何处,在本例中:

复制代码
内存表示                    值表示
    %q0         [%q0_0, %q0_1 ... %q0_L, %q0_M; %q0_P ... %q0_Y, %q0_Z]

我们知道一个 Hadamard 应用于 %q0_L 并生成 %q0_M,另一个应用于 %q0_Y 并生成 %q0_Z。因此,它们之间没有连接------这意味着它们不能相互抵消。

相关推荐
Qforepost1 天前
量子前哨+太平金科联合发布《量子计算赋能保险业的可行性分析报告》(2026)
量子计算
梦帮科技2 天前
QML-04-QGraph-Diff:量子非欧图扩散生成模型与 SE(3) 等变分子晶格逆向合成完整技术指南(上部分)
人工智能·算法·自动化·量子计算·傅里叶分析
梦帮科技2 天前
基于幺正李代数连续归一化流的混合量子生成模型 (HQNN-Flow) 完整技术指南(上部分)
网络·人工智能·算法·量子计算
Liaiyang666 天前
空圈容错·极限工程实战下篇——外部供给层怎么升维,内外层怎么联动
量子计算·脑机接口·1024程序员节·科学哲学·容错设计·系统思维·工程方法论
JZMSYYQ8 天前
超低温霍尔仪在量子计算中具体测什么
量子计算·霍尔效应·霍尔测试·霍尔效应测试·霍尔效应实验仪·超低温
量子客8 天前
中性原子量子计算公司,又多了一家
量子计算
量子客9 天前
「跨过纠错阈值」与「实用容错计算」之间,还有多远距离?
量子计算
简单风9 天前
量子科技入门(一)量子通信,它管的不是网速
科技·量子计算
frankzch11 天前
Claude 刷新量子电路最优:LLM 与评估器的进化循环怎么搭
人工智能·深度学习·机器学习·语言模型·量子计算
RichardLau_Cx13 天前
合肥科创产业生态解析:量子、可控核聚变、半导体与多元未来产业的技术布局
量子计算