4. Qiskit转译接口初探
在上一节中我们已经知道,Qiskit 中编写的量子电路是“逻辑电路”,它描述的是量子比特之间的抽象关系,并不关心这些比特在真实硬件上究竟位于哪个物理位置、支持哪些门、连接拓扑如何。而 transpile() 函数正是连接“逻辑电路”与“物理后端”的桥梁。本节我们围绕一次完整的基础转译,把输入、关键参数、转译过程与结果观察串起来。
一、转译到底在做什么
可以把转译理解为一次“编译”:输入是一段与硬件无关的 QuantumCircuit,输出是一段能够直接交给指定后端执行的电路。中间至少发生三类变换:
- 布局映射(Layout):把逻辑比特分配到后端的物理比特上,并记录映射关系;
- 路由(Routing):当双比特门作用在两个没有直接连线的物理比特上时,插入 SWAP 门把量子态搬运到相邻比特;
- 门分解与优化(Translation & Optimization):把电路中的门转换成后端原生门集合(basis gates),并在指定优化级别下做化简。
因此转译后的电路往往比原电路“更长”,多出来的部分主要来自 SWAP 和门分解,这是正常现象,而不是错误。
二、准备一个可观察的示例电路
为了让结构变化足够明显,我们构造一个包含 3 个量子比特、带有一个跨比特 CNOT 和若干单比特门的电路。示例参数均为教学假设,实际运行结果会随后端与 Qiskit 版本不同而变化。
from qiskit import QuantumCircuit, transpile
from qiskit_ibm_runtime import QiskitRuntimeService
qc = QuantumCircuit(3, 3)
qc.h(0)
qc.cx(0, 2) # 逻辑上 0 与 2 相互作用
qc.ry(0.4, 1)
qc.cx(1, 2)
qc.measure([0, 1, 2], [0, 1, 2])
print("原始电路深度:", qc.depth())
print("原始门数量:", qc.count_ops())
这里 cx(0, 2) 是关键:在逻辑层面 0 和 2 可以直接作用,但在真实芯片上它们未必相邻,这正是路由要解决的问题。
三、指定后端与优化级别
transpile() 的核心参数是 backend 与 optimization_level。前者决定目标硬件约束(耦合图、basis gates),后者取 0~3,数值越高优化越激进,编译耗时也越长。
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
tqc = transpile(
qc,
backend=backend,
optimization_level=1,
seed_transpiler=42, # 固定随机种子,便于复现
)
print("转译后深度:", tqc.depth())
print("转译后门数量:", tqc.count_ops())
print("使用的物理比特:", tqc.layout.final_index_layout())
几个值得注意的点:seed_transpiler 让布局与路由的随机选择可复现;tqc.layout 记录了逻辑比特到物理比特的映射,是判断“哪个逻辑比特跑到了哪”的依据;count_ops() 则直接反映门集合是否已被替换为后端原生门。
四、转译前后的结构对比
下图把一次典型转译的关键变化集中呈现:左侧是逻辑电路,右侧是转译结果,中间标出布局、路由与门分解三条作用路径,底部给出可直接对照的观察指标。
五、如何判读转译结果
拿到 tqc 后,建议按以下顺序检查,而不是只看深度一个数字:
- 门集合是否合规:
tqc.count_ops()中出现的门应全部属于backend.operation_names,若仍出现cx之外的抽象门,说明分解未完成或后端声明有误。 - 布局是否合理:通过
tqc.layout.final_index_layout()查看逻辑比特落点,若关键交互比特被分到相距很远的物理比特,SWAP 数量会明显上升。 - 深度与 SWAP 的代价:深度增加主要来自 SWAP 与单比特门分解。若 SWAP 数量异常多,可尝试提高
optimization_level或更换耦合更友好的后端。 - 测量映射:转译后测量仍作用在正确的物理比特上,最终结果按
layout反解回逻辑比特,这一步在后续结果处理中必须保持一致。
六、一次可复现的对比实验
把同一电路在级别 0 与级别 3 下各转译一次,记录指标,就能直观看到优化级别的影响。下表为教学示例的典型量级,实际数值以后端与版本为准:
| 指标 | 原始电路 | 级别 0 | 级别 3 |
|---|---|---|---|
| 电路深度 | 约 5 | 明显增大 | 相对级别 0 更小 |
| CNOT/SWAP 类双比特门 | 2 个 CNOT | 含额外 SWAP 分解 | SWAP 可能被合并减少 |
| 门集合 | H、CX、Ry | 后端原生门 | 后端原生门 |
| 编译耗时 | — | 最短 | 最长 |
seed_transpiler 并保存 layout 信息。完成本节后,你应当能够独立完成一次“构造逻辑电路 → 选择后端 → 指定优化级别 → 调用 transpile() → 对比深度、门统计与布局”的完整流程,并解释转译后电路为何变长、哪些变化来自路由、哪些来自门分解。这正是后续把电路真正提交到硬件或模拟器执行的基础。