2. 量子电路构建基础
在 Qiskit 中,QuantumCircuit 是描述量子程序的核心对象。它把“有哪些量子比特、按什么顺序施加哪些门、最后如何测量”这三件事组织成一份可执行、可绘制、可仿真的电路描述。本节围绕一个最小但完整的例子展开:创建 2 个量子比特和 2 个经典比特,制备 Bell 态,测量并运行在模拟器上分析结果。理解这条链路,就掌握了 Qiskit 量子应用开发的基本骨架。
一、寄存器:量子比特与经典比特的容器
量子电路需要两类寄存器。QuantumRegister 保存量子比特,是门操作的作用对象;ClassicalRegister 保存测量结果,是经典比特的容器。二者在电路中的角色不同:量子寄存器参与叠加、纠缠等量子演化,经典寄存器只接收测量后的 0/1 结果。
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
qr = QuantumRegister(2, 'q') # 2 个量子比特,命名 q
cr = ClassicalRegister(2, 'c') # 2 个经典比特,命名 c
qc = QuantumCircuit(qr, cr) # 将两类寄存器绑定到同一电路
也可以使用简写 QuantumCircuit(2, 2),Qiskit 会自动创建名为 q 和 c 的寄存器。显式创建寄存器的好处是命名清晰,便于在复杂电路中区分不同功能模块。需要注意:量子比特索引从 0 开始,qr[0] 是第一个量子比特,qr[1] 是第二个;经典比特同理。索引顺序决定了电路图中比特线的上下排列,也决定了测量结果字符串的位序。
二、门操作:从初始态到目标态
电路默认所有量子比特从 |0⟩ 态开始。门操作按调用顺序依次作用。构建 Bell 态的标准做法是:先对 qr[0] 施加 Hadamard 门产生叠加态,再以 qr[0] 为控制、qr[1] 为目标施加 CNOT 门产生纠缠。
qc.h(qr[0]) # H 门:|0> -> (|0> + |1>)/√2
qc.cx(qr[0], qr[1]) # CNOT:控制位 q0,目标位 q1
经过这两步,电路状态为 (|00⟩ + |11⟩)/√2。此时若直接测量,只会得到 00 或 11,各约 50%,而不会出现 01 或 10。这正是纠缠的典型特征:两个量子比特的结果完全关联。除 H 和 CNOT 外,常用门还包括 X、Y、Z、S、T、RX、RY、RZ 等单比特门,以及 cz、swap、ccx 等多比特门。门的作用对象可以是单个量子比特、控制-目标对,也可以是整个寄存器。
三、测量:把量子信息转为经典结果
测量使用 measure 方法,把指定量子比特的测量结果写入指定经典比特。常见写法是整体测量:
qc.measure(qr, cr) # q[0]->c[0], q[1]->c[1]
也可以逐位指定,例如 qc.measure(qr[0], cr[0])。测量会破坏量子叠加,使量子比特坍缩到 |0⟩ 或 |1⟩,因此测量通常放在电路末尾。若在测量后继续施加量子门,后续演化将基于坍缩后的经典确定态,而不是原来的叠加态。测量结果字符串的位序约定为:最右侧对应最低索引经典比特。例如结果 '10' 表示 c[1]=1、c[0]=0。
四、绘制电路图与运行模拟器
Qiskit 提供 qc.draw() 直接输出文本电路图,便于快速检查门和测量的位置:
print(qc.draw())
# ┌───┐ ┌─┐
# q_0: ┤ H ├──■───┤M├
# └───┘┌─┴─┐└╥┘
# q_1: ─────┤ X ├─╫─
# └───┘ ║
# c: 2/═══════════╩═
# 0
运行仿真使用 Aer 的 qasm_simulator,通过 transpile 转换后交给 backend.run 执行,并指定采样次数 shots:
from qiskit import transpile
from qiskit_aer import AerSimulator
sim = AerSimulator()
tqc = transpile(qc, sim)
job = sim.run(tqc, shots=1024)
result = job.result()
counts = result.get_counts()
print(counts) # 例如 {'00': 512, '11': 512}
结果是一个字典,键为测量比特串,值为出现次数。对 Bell 态,理想情况下 00 和 11 各占约一半,01 和 10 接近 0。由于模拟器采样具有统计涨落,1024 次采样下比例不会精确等于 50%,但偏差通常在几个百分点以内。若 01 或 10 明显出现,说明电路构建有误,例如 CNOT 控制位与目标位写反,或 H 门作用在了错误的比特上。
五、结果分析与常见问题
拿到 counts 后,第一步是看哪些比特串出现、比例如何。对 Bell 态,判断标准是:00 与 11 的次数接近且合计接近总 shots,01 与 10 接近 0。若结果不符合预期,可按以下顺序排查:
- 门顺序:H 必须在 CNOT 之前,否则无法产生纠缠。
- 控制位与目标位:
qc.cx(qr[0], qr[1])中第一个参数是控制位,第二个是目标位,写反会得到不同结果。 - 测量映射:确认
measure的量子比特与经典比特对应关系,避免结果位序读错。 - shots 数量:shots 太少时统计涨落大,建议至少 1024 次;shots 越多,比例越接近理论值。
- 是否 transpile:真实后端或部分模拟器需要先转换,直接运行原始电路可能报错。
print(qc.draw()) 确认电路结构,再运行模拟器,最后把 counts 与理论分布对照。三步走能快速定位绝大多数入门阶段的电路错误。把上述流程串起来,就是 Qiskit 量子程序的最小闭环:用寄存器声明资源,用门操作描述演化,用测量提取经典信息,用模拟器采样并分析统计结果。后续更复杂的算法,本质上都是在这个骨架上增加量子比特、增加门、增加测量分组,并配合更精细的结果处理。