第一个 Bell 线路¶
这次实验准备两个量子比特,测量它们,再读取运行结果。你会看到:即使线路不变,每次采样得到的频率也可能不同。
先完成安装,在仓库根目录运行下面的命令。实验使用两个量子比特和 32 次采样,在本地 CPU 上运行。
先预测会测到什么¶
两个量子比特最初都处于 0 状态。对第 0 个量子比特施加 H 门,使它进入叠加态。随后执行 CX 门:当第 0 个量子比特为 1 时,翻转第 1 个量子比特。两步操作准备出 Bell 态:
(|00⟩ + |11⟩) / √2
在这个基上进行理想测量,00 和 11 的概率各为 1/2。运行前想一想:采样 32 次,是否一定会各得到 16 次?
构建并运行线路¶
下面的源码也是课程自动检查时运行的文件。measure_all(key="readout") 为测量寄存器命名。一个 shot 表示从输出分布中采样一次,seed 用于控制伪随机采样。
"""构建 Bell 线路并解释本地采样结果。
示例使用链式 ``Circuit`` API 添加量子门和终端测量。读取 counts 时要同时查看
bit order,否则无法判断 bitstring 的每一位对应哪个量子比特。
"""
from __future__ import annotations
import json
from cascaqit import Circuit
def main() -> None:
"""使用固定随机种子执行一个两量子比特纠缠线路。"""
# H 门创建叠加态,CX 门让 q1 与 q0 产生关联。
circuit = Circuit(2, program_id="lesson.digital.beginner")
circuit.h(0).cx(0, 1).measure_all(key="readout")
# 对第一次 Digital 实验而言,Circuit.run 是最短的本地执行路径。
result = circuit.run(shots=32, seed=201, return_probabilities=True)
program = circuit.to_program()
payload = {
"track": "digital_developer",
"level": "beginner",
"lesson": "bell_circuit",
"facts": {
"gate_names": [
operation.definition.name
for operation in program.circuit.operations
if operation.definition.name != "measure"
],
"counts_total": sum(result.counts.values()),
"probability_states": sorted((result.probabilities or {}).keys()),
"bit_order": result.metadata["bitstring_ordering"]["qubit_order"],
"measurement_key": program.circuit.classical_registers[0].register_id,
},
"boundaries": {
"hardware_execution": False,
"cloud_execution": False,
"network_accessed": False,
"credentials_loaded": False,
},
}
print(json.dumps(payload, sort_keys=True))
if __name__ == "__main__":
main()
python3 examples/user/tracks/digital_developer/01_beginner_bell_circuit_zh.py
脚本打印一个 JSON 对象,先阅读 facts:
{
"boundaries": {
"cloud_execution": false,
"credentials_loaded": false,
"hardware_execution": false,
"network_accessed": false
},
"facts": {
"bit_order": [
"q0",
"q1"
],
"counts_total": 32,
"gate_names": [
"h",
"x"
],
"measurement_key": "readout",
"probability_states": [
"00",
"01",
"10",
"11"
]
},
"lesson": "bell_circuit",
"level": "beginner",
"track": "digital_developer"
}
| 字段 | 要检查什么 |
|---|---|
gate_names |
应为 ["h", "x"];受控 X 操作保存的门名为 x,控制信息记录在操作对象中 |
counts_total |
是否等于指定的 32 次采样 |
probability_states |
概率结果中记录了哪些状态;判断概率时还要看数值,不能只看键是否存在 |
bit_order |
字符串的每一位对应哪个量子比特 |
measurement_key |
是否为刚才指定的寄存器名 readout |
boundaries 说明这次运行使用本地模拟。它不是错误提示,也不表示你还需要配置云账户。
查看实际采样计数¶
课程脚本默认只打印摘要。若要查看计数,在本地副本的 result = circuit.run(...) 后加入 print(result.counts)。再加入 print(result.probabilities),对比采样频率与理想概率。
计数总和应为 32,但不必恰好各占 16 次。重复测量不会改变理想概率分布,只会从这个分布中重新采样。固定 seed 有助于在相同环境中重复实验;不要把某组采样整数视为跨版本保证。
00 和 11 的计数说明两个量子比特在这个测量基上有关联。但仅凭这些计数,无法区分 Bell 态和经典混合态;研究相干性还需要考虑其他测量基。另外,这个对称例子本身也不能暴露位序是否颠倒,仍要读取位序元数据。
改两个条件试试¶
- 把 shots 从 32 改为 1,000,对比采样频率与 1/2 的差距。差距是否变小?换几个 seed 再判断。
- 去掉
.cx(0, 1),保留 H 门和测量。现在只有哪个量子比特可能变化?结合bit_order解释输出字符串。
核对思路
增加 shots 通常会减小相对采样波动,但不能保证任意两次运行都恰好如此。去掉 CX 后,只有第 0 个量子比特进入叠加态,第 1 个仍为 0。读取记录的位序,判断它在字符串中的位置。