量子伴随自动微分
适用版本 · ArcQML 0.1.0
本页目录
前向定义
对于按执行顺序排列的多个量子门,ArcQML 的 run 从初态开始逐门演化得到最终态,并计算 Hamiltonian 的期望值。第 k 个门对应的状态演化和最终目标函数定义为:
若初态或任一 Circuit Parameter 需要梯度,且当前线程启用梯度记录,run 会保存最终态、Hamiltonian 作用于最终态的结果、已绑定操作和参数槽位映射,并创建一个自定义 F64 Tensor autograd 节点。否则它只执行前向,不保存伴随上下文。
单态伴随反向公式
设外层实标量损失为 L,单态期望值为 f,标量上游梯度为 g = ∂L/∂f。为避免重复计入上游权重,以下公式使用未缩放的伴随态:
按逆序施加门的共轭转置可以恢复每个门的输入态。参数 p 在多个门中出现时,梯度为各处贡献之和:
实现可在反向开始时把 g 乘入伴随缓冲区,此后不再额外乘 g。若初态需要梯度,ArcQML 返回的复梯度采用 ∂L/∂Re(ψ₀) + i ∂L/∂Im(ψ₀) 约定:
它等于两倍的共轭 Wirtinger 偏导,不应与未乘 2 的偏导符号混用。
参数梯度则按照 Parameter 的 F32 或 F64 dtype 构造成标量 Tensor。该过程只需保存最终态和已绑定门信息,不需要保存每一层完整状态。
batch 的上游梯度与 VJP
batch run 的输出不是标量而是 [B] 向量,因此它本身不能直接调用无参 backward()。通常应先用 mse_loss 或二元 logits 交叉熵等经典损失函数将其归约为标量。若上层图传回 grad_output,batch 伴随节点要求它是 shape 为 [B] 的 F64 Tensor,并把每个上游梯度乘到对应 batch 行的 adjoint_state 中。
因此 batch 模式实现的是向量-雅可比积(VJP):外部经典网络或损失决定每个样本输出的上游权重,量子伴随器再将其回传到共有 Circuit 参数和可微初态。
no_grad 与训练图内存
用 no_grad() 或 Python 的 with arcqml.no_grad(): 包围 run 时,records_gradients 为 false,运行不保留伴随上下文,返回普通前向 Tensor。验证、推理、基准测试和只读状态分析应采用此模式;需要反向时,不应先把预测转为 f64 或 NumPy 数组,因为那会离开 Tensor 图。
Rust 必须绑定作用域守卫,单独执行 no_grad(); 会在语句结束时立即恢复记录:
{
let _guard = no_grad();
let prediction = simulator.run(&circuit, &observable)?;
// 在此作用域内读取 prediction。
}
梯度记录开关仅作用于当前线程。Python 当前应每次新建上下文,即使用 with arcqml.no_grad():;不要缓存或重复进入同一个上下文对象。