4. 测量操作与寄存器绑定
在 Qiskit 中,量子线路的测量并不是“自动发生”的:必须显式调用 measure 指令,把某个量子比特的测量结果写入某个经典比特。这条指令同时携带两个信息——测哪个量子比特和结果存到哪个经典比特。理解这种“量子比特 → 经典比特”的映射关系,是读懂测量结果、正确解读计数(counts)以及后续做条件控制的前提。
一、measure 的两个参数:量子端与经典端
最基础的写法是 QuantumCircuit.measure(qubit, cbit),它等价于向线路追加一条 Measure 指令。第一个参数是量子比特(可以是整数索引,也可以是 Qubit 对象),第二个参数是经典比特(整数索引或 Clbit 对象)。语义非常直接:对该量子比特执行计算基(Z 基)测量,把得到的 0 或 1 写入指定经典比特。
from qiskit import QuantumCircuit
qc = QuantumCircuit(2, 2) # 2 个量子比特 q0,q1;2 个经典比特 c0,c1
qc.h(0) # 让 q0 处于叠加态
qc.measure(0, 0) # q0 的测量结果 → c0
qc.measure(1, 1) # q1 的测量结果 → c1
这里 QuantumCircuit(2, 2) 的两个参数分别是量子寄存器与经典寄存器的位宽。经典比特不是“可有可无的附属品”,它决定了结果能保存多少位、以什么顺序呈现。若只写 QuantumCircuit(2),线路没有经典寄存器,此时调用 measure(0, 0) 会因找不到经典比特而报错——这是初学者最常见的错误之一。
二、单比特测量与多比特测量
单比特测量就是上面那样逐条指定。多比特测量有两种常见写法。第一种是逐条列出,语义最清晰,适合映射关系不规则的情况:
qc.measure(0, 1) # q0 → c1
qc.measure(1, 0) # q1 → c0(交叉映射)
第二种是使用 measure 的批量形式,传入两个等长的列表,按位置一一配对:
qc.measure([0, 1], [0, 1]) # q0→c0, q1→c1
# 等价于 qc.measure(0,0); qc.measure(1,1)
批量写法要求两个列表长度一致,否则会抛出错误。它并不改变语义,只是把多条指令压缩成一行。需要强调的是:批量写法按“位置”配对,而不是按“名字”配对。因此 measure([0,1],[1,0]) 表示 q0→c1、q1→c0,是一个交叉映射,而不是“把 q0 存到 c0”。
qc.measure_all()。它会自动添加经典寄存器并把每个量子比特测量到同索引的经典比特;而 qc.measure_active() 只测量当前有门操作的量子比特。两者都会改变线路的寄存器结构,使用前应确认经典比特的最终布局。三、映射关系如何影响结果解读
测量完成后,通常用 transpile + run(或 Sampler 原语)执行,得到形如 {'01': 512, '10': 488} 的计数字典。这里的比特串顺序遵循 Qiskit 的约定:最右侧是最低位,对应 c0。也就是说,字符串 '01' 表示 c1=0、c0=1。如果映射是交叉的(q0→c1、q1→c0),那么读到 '01' 时,实际是 q0 测得 1、q1 测得 0。映射一旦写错,结果解读就会整体“镜像”或错位,而线路本身不会报错——这是最隐蔽的一类问题。
四、映射与线路结构的一致性检查
在把测量接入更复杂的线路(尤其是含条件控制、多寄存器或子线路)之前,建议做一次“映射自检”。最直接的办法是打印线路:print(qc.draw()) 会显示每个测量门连到哪根经典线;qc.count_ops() 可确认 measure 的数量是否等于预期。对于交叉映射,还可以在测量前加一个已知态做小规模验证,例如把 q0 置为 |1⟩、q1 置为 |0⟩,执行后若得到 '01',说明 c0 确实接的是 q0。
另一个容易忽略的点是经典寄存器的“命名”。当线路包含多个经典寄存器(如 cr1、cr2)时,measure(q, cr[i]) 中的索引是寄存器内索引,而不是全局经典比特编号。最终计数字典的比特串顺序由所有经典寄存器拼接决定,拼接顺序与寄存器添加顺序相关。因此在多寄存器场景下,务必用 qc.cregs 确认顺序,再对照比特串解读结果。
五、常见写法对照
| 写法 | 语义 | 适用场景 |
|---|---|---|
qc.measure(0, 0) | q0 → c0 | 单比特、映射明确 |
qc.measure([0,1],[0,1]) | q0→c0, q1→c1 | 规则一一对应 |
qc.measure([0,1],[1,0]) | q0→c1, q1→c0 | 需要交叉映射 |
qc.measure_all() | 全部量子比特 → 同索引经典比特 | 快速整体测量 |
qc.measure_active() | 仅有门操作的量子比特 → 经典比特 | 稀疏线路、减少冗余 |
小结:measure 的核心是“量子端 + 经典端”的配对。单比特逐条写、多比特用等长列表批量写,二者语义一致;真正决定结果解读的是映射关系与比特串顺序约定(最右为 c0)。写完后用 draw() 核对连线、用已知态做小验证,就能把“测量写对了但结果读反了”这类问题挡在运行之前。