寄存器管理¶
寄存器是 PySparQ "寄存器级编程"(Register Level Programming)的核心抽象。与传统的量子比特级编程不同,PySparQ 将操作层面提升到量子寄存器,使算法开发更加直观。
寄存器的本质¶
系统中的寄存器托管了 n 个 uint64_t 的存储。每个寄存器拥有名称、类型和比特宽度,其值以 uint64_t 存储。这种设计允许我们将量子态编码为类似 \(|a\rangle|b\rangle|c\rangle\) 的多寄存器形式,而无需关心底层量子比特的编码方式。
例如,QRAM 访问 \(|i\rangle|0\rangle \to |i\rangle|d[i]\rangle\) 只需要一个地址寄存器 i 和一个数据寄存器 d,QRAMLoad 算子直接在寄存器级别完成映射,完全不需要管理量子比特。
其中每个 \(|a_j\rangle |b_j\rangle |c_j\rangle\) 对应一个 System 中的 registers 数组。
添加寄存器:AddRegister¶
添加寄存器等价于与 \(|0\rangle\) 寄存器做直积(tensor product)。新寄存器在所有现有基态中的初始值为 0。
import pysparq as ps
ps.System.clear()
ps.System.add_register("a", ps.UnsignedInteger, 4)
state = ps.SparseState()
# 添加寄存器 "b":等价于 |a⟩ ⊗ |0⟩
ps.AddRegister("b", ps.UnsignedInteger, 4)(state)
# state 中所有基态的 "b" 值为 0
ps.pprint(state)
AddRegister 会同时更新静态元数据(name_register_map)和所有现有基态的寄存器值。
也可以使用 AddRegisterWithHadamard 在添加寄存器的同时施加 Hadamard,直接创建均匀叠加态:
# 添加 "q" 并创建 |0⟩, |1⟩, ..., |2^n - 1⟩ 的均匀叠加
ps.AddRegisterWithHadamard("q", ps.UnsignedInteger, 2)(state)
删除寄存器:RemoveRegister¶
删除寄存器等价于对该寄存器做 PartialTrace(偏迹),即消除该寄存器对量子态的贡献。在模拟中,这相当于测量该寄存器后丢弃测量结果的效果。
# 删除寄存器 "b":等价于对 "b" 做 PartialTrace
ps.RemoveRegister("b")(state)
重要
RemoveRegister 在执行前会检查该寄存器是否与剩余寄存器存在纠缠(通过 TestRemovable)。如果存在纠缠,删除操作会抛出异常,因为此时对单个寄存器的 PartialTrace 不能简单地等价于丢弃。
拆分寄存器:SplitRegister¶
SplitRegister 将一个寄存器拆分为两个:原寄存器保留高位,新寄存器获取低位。
ps.System.clear()
ps.System.add_register("full", ps.UnsignedInteger, 8)
state = ps.SparseState()
ps.Init_Unsafe("full", 0b10110011)(state)
# 拆分:原 "full" 保留高 4 位,新 "low" 获取低 4 位
ps.SplitRegister("full", "low", 4)(state)
# "full" = 0b1011(高 4 位),"low" = 0b0011(低 4 位)
拆分过程:
添加新寄存器(获取低位)
缩小原寄存器的比特宽度
在所有基态中,将原值的高位保留在原寄存器,低位写入新寄存器
合并寄存器:CombineRegister¶
CombineRegister 将两个寄存器合并为一个:第一个寄存器的值左移后拼接第二个寄存器的值。
# 合并:"full" = (full << 4) + low
ps.CombineRegister("full", "low")(state)
# "full" = 0b10110011
合并过程:
扩展第一个寄存器的比特宽度(加上第二个的宽度)
在所有基态中,将第一个寄存器的值左移第二个的宽度后加上第二个的值
删除第二个寄存器
PartialTrace:测量¶
在 PySparQ 中,PartialTrace 被等价视为测量操作。这在模拟层面是合理的——对某些寄存器进行偏迹等同于对它们进行测量并丢弃结果。
PartialTrace 提供三种模式:
类 |
行为 |
返回值 |
|---|---|---|
|
随机测量:按概率分布随机选择测量结果,然后坍缩态 |
|
|
选择性坍缩:保留指定寄存器值为指定值的基态,归一化其余基态 |
归一化概率 |
|
范围坍缩:保留指定寄存器值在给定范围内的基态 |
归一化概率 |
import pysparq as ps
ps.System.clear()
ps.System.add_register("a", ps.UnsignedInteger, 2)
ps.System.add_register("b", ps.UnsignedInteger, 2)
state = ps.SparseState()
ps.Hadamard_Int("a")(state)
ps.Hadamard_Int("b")(state)
# 随机测量寄存器 "a"
measured_values, prob = ps.PartialTrace("a")(state)
print(f"测量结果: {measured_values}, 概率: {prob}")
# state 中 "a" 的值坍缩为测量结果
# 选择性坍缩:强制 "b" = 2
prob = ps.PartialTraceSelect("b", [2])(state)
# 只保留 "a" = 1 的基态并归一化
prob = ps.PartialTraceSelect("a", [1])(state)
寄存器栈操作:Push / Pop¶
Push 和 Pop 提供临时寄存器的栈管理,适用于算法中需要临时变量的场景:
# Push:将临时寄存器入栈
ps.Push("temp", ps.UnsignedInteger, 4)(state)
# 使用临时寄存器进行计算...
# Pop:弹出临时寄存器
ps.Pop()(state)
寄存器操作与量子态的关系总结¶
操作 |
物理意义 |
对量子态的影响 |
|---|---|---|
|
与 \(|0\rangle\) 直积 |
所有基态增加一个值为 0 的寄存器 |
|
PartialTrace(测量后丢弃) |
消除该寄存器,前提是无纠缠 |
|
将一个子系统拆分为两个 |
基态数量不变,寄存器数加 1 |
|
将两个子系统合并为一个 |
基态数量不变,寄存器数减 1 |
|
测量 |
按概率坍缩态,基态数量减少 |
|
临时寄存器入栈/出栈 |
辅助操作,保存/恢复寄存器状态 |
API 参考¶
寄存器管理算子的完整 API 文档,请参见以下算子参考页面:
或查阅 算子分类详解 章节获取所有算子的完整列表。