最近我把 DREAMVFIA 这个开源项目重新梳理了一遍,代码库、文档、示例工程全都收拾干净,总算敢拿出来见人了。这个项目名字绕口,但它想干的事很具体:把量子隐形传态(quantum teleportation)从教科书里的公式变成一台普通笔记本电脑上就能跑通的实验,再一步步延伸到真实量子硬件上验证。
为什么要做这么一件事?因为我发现很多想入门量子信息的人,卡住的地方往往不是数学,而是"我知道了公式,但不知道它跟电路有什么关系"。量子隐形传态又是最经典、最能体现量子纠缠价值的入门实验。DREAMVFIA 的思路就是给你一条完整的链路:理论推导、仿真电路、保真度验证、真机实验,每一步都有代码和可视化结果对照。这篇文章相当于项目的完整笔记,也写给所有想亲手跑一次隐形传态实验的人。
1. 项目整体设计与思路拆解
1.1 量子隐形传态到底"传"的是什么
先说清楚一个最容易误解的点:量子隐形传态传的不是物体,不是能量,甚至不是传统意义上的信息内容,而是量子态。
想象你有一封信,信封里装着一张写了字的纸。传真机做的事情,是扫描这张纸上的图案,把图案信息传到另一端,再重新打印出一张外观一样的纸。量子隐形传态更极端:它不扫描量子态的具体数值(实际上也不可能扫描,因为测量会破坏量子态),而是靠两份共享的经典信息加一份预共享的量子纠缠,把"量子态"本身从 Alice 手里转移到 Bob 手里。
这里有个关键限制——量子不可克隆定理。经典信息可以无限复制,但量子态不可以。你没法做一个"量子复印机",把 |ψ⟩ 复制成两份一模一样的。所以量子隐形传态的核心不是复制,而是转移:Alice 这边原来的量子态在协议完成后已经坍缩成乱七八糟的测量结果,有用的信息全部转移到了 Bob 那边。这就像把一份绝版手稿原件寄给对方,自己手里只剩灰烬,但对方拿到的是完整原件。
1.2 为什么非要做成开源项目
量子隐形传态的概念在很多科普文章里被讲得神乎其神,什么"瞬间移动""超光速通信"都来了。但如果你真去读原始论文或者翻教科书,会发现中间的跨度非常大:从密度矩阵、纠缠态、贝尔测量到量子电路,每一层都会劝退一批人。
大部分学术代码又丑又难跑,注释稀少,依赖一堆过时的库。我当年踩坑的时候就想,如果有一个项目能把隐形传态的完整流程整理清楚,每个模块都拆开讲明白,开箱即用,能省多少时间。DREAMVFIA 就是补这个空缺的。
它解决的核心问题有三个:
- 理论到电路的映射:把教科书里的公式一步一歩翻译成量子门操作;
- 实验流程的完整性:从制备纠缠、贝尔测量、经典通信到 Bob 端恢复,一条龙覆盖;
- 仿真与真机的统一:同一套代码,改一行配置就能从本地仿真器切换到真实量子硬件。
适用的人群也很广:正在学量子信息课程的学生,刚接触量子计算想找练手项目的开发者,还有做量子网络方向研究但需要一个稳定 baseline 的研究人员,都能从里面找到自己需要的东西。
1.3 DREAMVFIA 的架构总览
整个项目基于 Python 3.10+,主要依赖 Qiskit、QuTiP、NumPy 和 Matplotlib。Qiskit 负责电路构建和执行,QuTiP 用来做密度矩阵校验,Matplotlib 负责画布洛赫球和保真度曲线。
架构上分四层:
- 理论校验层:预先计算理论预期的末态,和实验测量结果做比对;
- 线路构建层:把隐形传态协议拆成四个子模块——态制备、纠缠建立、贝尔测量、条件恢复;
- 后端适配层:抽象出统一的 backend 接口,本地仿真和真实量子设备都实现这套接口;
- 可视化层:布洛赫球、密度矩阵热力图、保真度随参数变化曲线。
这样设计的好处是每一层都可以独立测试和替换。比如你想换一种纠缠态生成方式,只需要改entanglement.py;想换一个量子硬件平台,只需要实现一个新的 backend 类。
dreamvfia/ ├── dreamvfia/ │ ├── core/ │ │ ├── state_prep.py │ │ ├── entanglement.py │ │ ├── bell_measure.py │ │ └── recovery.py │ ├── backends/ │ │ ├── base.py │ │ ├── local.py │ │ └── ibm.py │ ├── utils/ │ │ ├── fidelity.py │ │ └── plot.py │ └── cli.py ├── examples/ │ └── teleport_demo.py ├── tests/ └── docs/2. 理论速成:量子比特、纠缠态与测量
2.1 量子比特与叠加态
传统比特只有 0 和 1 两种状态。量子比特(qubit)不同,它可以处于叠加态:
|ψ⟩ = α|0⟩ + β|1⟩
其中 α 和 β 是复数概率幅,满足 |α|² + |β|² = 1。测量这个量子比特时,得到 |0⟩ 的概率是 |α|²,得到 |1⟩ 的概率是 |β|²。如果你不去测量它,它就同时"包含"0 和 1 的信息,这就是量子并行性的来源。
用一个生活化的类比:经典比特像一个开关,要么开要么关;量子比特像一个旋转中的硬币,在没有落地之前,它同时处于正面和反面的叠加状态,落地(测量)时才决定到底哪一面朝上。
不过叠加态并不只是概率,还有一个重要的东西叫相位。α 和 β 之间的相对相位会带来物理上的差异,这在隐形传态中会通过 Z 门体现出来。
2.2 贝尔态:量子纠缠的原子单位
量子纠缠是隐形传态的资源。最简单的纠缠态是贝尔态,四个最大纠缠态长这样:
|Φ⁺⟩ = (|00⟩ + |11⟩) / √2 |Φ⁻⟩ = (|00⟩ - |11⟩) / √2 |Ψ⁺⟩ = (|01⟩ + |10⟩) / √2 |Ψ⁻⟩ = (|01⟩ - |10⟩) / √2
在 |Φ⁺⟩ 这个态里,如果你测量第一个量子比特得到 |0⟩,第二个量子比特一定也是 |0⟩;测到 |1⟩ 则第二个也必然是 |1⟩。两个粒子之间没有任何"信号传递",但它们的测量结果呈现出完美的关联。爱因斯坦把这种现象称为"幽灵般的超距作用",但现在我们知道它并不违反相对论,因为它不能用来超光速传递信息。
制备贝尔态的标准方法很简单:对第一个粒子做 H 门,再用 CNOT 门把它和第二个粒子纠缠起来。这是量子电路中"制造纠缠"的最基本配方,后面实验里会反复用到。
2.3 测量与坍缩
测量是量子力学里最"不讲道理"的操作。对一个叠加态做测量,得到的结果由概率决定,测量之后量子态立即坍缩到对应的本征态上。也就是说,测量不是"看一看",而是"强迫它做决定"。
在隐形传态协议里,Alice 要对两个量子比特做一次贝尔基测量,也就是把测量结果投影到四个贝尔态上。实验结果只会是四种之一:|Φ⁺⟩、|Φ⁻⟩、|Ψ⁺⟩、|Ψ⁻⟩,每种结果对应 2 比特经典信息:00、01、10、11。
注意:贝尔基测量不等于分别测量两个比特再组合。它需要先用 CNOT 加 H 门把贝尔基"解码"成计算基,然后才能用普通测量读出结果。这是隐形传态电路里最容易被看晕的地方,第 4 章会详细讲。
2.4 隐形传态协议逐行推导
假定 Alice 手上有一个未知量子态 |ψ⟩ = α|0⟩ + β|1⟩,她想把这个态传给远处的 Bob。她和 Bob 预先共享一个纠缠对 |Φ⁺⟩ = (|00⟩ + |11⟩) / √2。
整个系统的初态是:
|ψ⟩ ⊗ |Φ⁺⟩ = (α|0⟩ + β|1⟩) ⊗ (|00⟩ + |11⟩) / √2
三项展开后会得到四个分量,关键在于 Alice 对前两个粒子做贝尔基测量。无论待传态是什么,测量结果都等概率地落在四种贝尔态之一,而 Bob 手上的粒子会根据测量结果坍缩成四种状态之一:
| Alice 测量结果 | 经典比特 | Bob 粒子坍缩后的状态 | Bob 需要做的操作 |
|---|---|---|---|
| Φ⁺⟩ | 00 | α | |
| Φ⁻⟩ | 01 | α | |
| Ψ⁺⟩ | 10 | α | |
| Ψ⁻⟩ | 11 | α |
Bob 拿到 Alice 通过经典信道(比如电话、互联网)发来的 2 比特信息后,只要对号入座做相应的量子门操作,就能把手上的粒子精确恢复成 Alice 当初的未知态。
这里必须强调两点。第一,隐形传态不是瞬时的。Bob 必须等 Alice 的经典信息到达才能完成恢复,经典信息的传送速度不可能超过光速,所以信息没有以超光速传播。第二,量子态没有被复制。Alice 原本的态在测量时已经破坏掉了,Bob 得到的是"转移"而非"复印",这正好不违背量子不可克隆定理。
3. 环境搭建与 DREAMVFIA 核心实现
3.1 安装与初始化
先把项目克隆到本地,创建虚拟环境,装依赖:
git clone https://github.com/yourname/dreamvfia.git cd dreamvfia python -m venv .venv source .venv/bin/activate pip install -r requirements.txt pip install -e .安装完成后可以用命令行工具快速体验:
dreamvfia init --demo dreamvfia run --config config.yaml dreamvfia viz --type blochinit会在当前目录生成一个示例工程和默认配置,run执行隐形传态全流程,viz打开可视化面板。第一次跑的时候建议用本地仿真器,速度很快,几秒钟就能出结果。
3.2 核心模块职责说明
四个核心模块对应协议的四个步骤,我按职责拆开写,方便阅读和复用。
state_prep.py负责制备待传态。代码里用一个u3(theta, phi, lam)门来生成任意单比特态。entanglement.py负责建立 Alice 和 Bob 之间的纠缠对,封装了 H 门加 CNOT 门那套标准配方。bell_measure.py是最关键的一层,实现贝尔基测量,它先把 CNOT 门施加在待传态和 Alice 的纠缠粒子上,再对待传态做 H 门,然后测量两个量子比特。recovery.py根据经典比特应用条件恢复门。
为什么把贝尔测量拆成单独的模块?因为它是整个协议里最容易出错也最值得反复琢磨的地方。单独抽出来,配合注释和测试,你能清晰地看到它做了什么、为什么这么做。
def bell_measure(qc, q0, q1, c0, c1): qc.cx(q0, q1) qc.h(q0) qc.measure(q0, c0) qc.measure(q1, c1)3.3 后端适配:本地仿真器与真实硬件
DREAMVFIA 设计了一个backend抽象层,本地仿真和真实设备都统一接口。默认的本地后端基于 Qiskit Aer 的AerSimulator,可以模拟理想情况下的量子电路。如果你想上真机,只需要在配置文件里切换:
backend: name: ibm device: ibm_brisbane shots: 4096 optimization_level: 3真实设备需要先配置 IBM Quantum 的账号凭据。社区版账号可以免费使用一些公开设备,只是要排队。切换后端之后,代码逻辑完全不用改,这就是抽象层的好处。
真机实验和仿真有一个巨大的差异:真实设备有噪声。门的保真度不是 100%,测量也存在误差,所以必须跑多次实验取统计结果,不能只跑一次。后面第 5 章会细说。
3.4 配置文件的含义
默认的config.yaml长这样:
teleport: theta: 1.5708 phi: 0.7854 lam: 0.0 backend: name: local shots: 8192 noise_model: false fidelity: target_state: customtheta、phi、lam决定待传态的具体参数。1.5708是 π/2,配合phi=0.7854(π/4),对应的量子态是 cos(π/4)|0⟩ + e^{iπ/4} sin(π/4)|1⟩,也就是一个既不在 |0⟩ 也不在 |1⟩ 上的叠加态,适合用来验证隐形传态是否真的传对了。shots是测量次数,仿真器设 8192 次足够看到稳定的概率分布。noise_model开启后可以模拟带噪声的测量结果,更接近真实硬件的行为。
4. 完整实验流程:从线路构建到保真度验证
4.1 第一步:制备待传态
假设 Alice 要传递的量子态参数是 theta = π/2,phi = π/4。代码里用 Qiskit 的u门来制备:
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister q = QuantumRegister(3, 'q') c = ClassicalRegister(2, 'c') qc = QuantumCircuit(q, c) theta = 1.5708 # π/2 phi = 0.7854 # π/4 lam = 0.0 qc.u(theta, phi, lam, q[0])q[0] 是 Alice 要传递的未知态,q[1] 是 Alice 的纠缠粒子,q[2] 是 Bob 的纠缠粒子。
4.2 第二步:建立共享纠缠对
接下来在 q[1] 和 q[2] 之间建立 |Φ⁺⟩ 纠缠态:
qc.h(q[1]) qc.cx(q[1], q[2])H 门把 q[1] 变成叠加态 (|0⟩ + |1⟩)/√2,CNOT 门将 q[2] 与 q[1] 关联起来。这一步之后,q[1] 和 q[2] 就处于最大纠缠态了。这组操作在任何教科书里都是生成 EPR 对的标准方法。
4.3 第三步:Alice 执行贝尔基测量
这是整个电路里最核心也最容易懵的一步。Alice 要对自己的 q[0] 和 q[1] 做贝尔基测量,但她不能直接测出"处于哪个贝尔态",因为贝尔态不是计算基。解决方案是:先做一个逆变换,把贝尔基映射回计算基,然后再测量。
qc.cx(q[0], q[1]) qc.h(q[0]) qc.measure(q[0], c[0]) qc.measure(q[1], c[1])CNOT 加 H 门的作用可以理解为把 |Φ⁺⟩、|Φ⁻⟩、|Ψ⁺⟩、|Ψ⁻⟩ 这四个纠缠态"解码"成 |00⟩、|01⟩、|10⟩、|11⟩。之后再测量,得到的就是普通比特,Alice 就可以把这 2 比特的测量结果传给 Bob 了。
4.4 第四步:经典信道传递结果
Alice 测量完之后,q[0] 和 q[1] 已经坍缩成了经典结果,但 Bob 的粒子 q[2] 还处于一种"未确定"的状态。它具体处于四种状态中的哪一种,完全取决于 Alice 的测量结果。
这时 Alice 必须把两个经典比特通过经典信道告诉 Bob。这个信道可以是任何经典通信手段:网络、电话、甚至写信都行。这也是为什么隐形传态不能超光速——瓶颈在经典通信上。
4.5 第五步:Bob 的条件恢复操作
Bob 拿到两个经典比特后,根据查表规则对 q[2] 施加恢复门:
qc.x(q[2]).c_if(c[1], 1) qc.z(q[2]).c_if(c[0], 1)这里的逻辑是:如果 c[1] 为 1,就对 q[2] 做 X 门;如果 c[0] 为 1,就对 q[2] 做 Z 门。两个都触发时,先 X 后 Z。
为了验证结果,我在 DREAMVFIA 里加了一个fidelity工具。它会在电路执行完后,把 Bob 粒子最终的量子态和理论预期待传态做对比,算出保真度。保真度等于 1 意味着完美传输。
4.6 验证结果:保真度计算与可视化
完整跑一次仿真,用 Qiskit 的 AerSimulator 执行电路:
from qiskit_aer import AerSimulator from qiskit.quantum_info import Statevector, state_fidelity sim = AerSimulator() result = sim.run(qc, shots=8192).result() counts = result.get_counts(qc) print(counts)仿真器的输出会显示四个测量结果的分布,比如:
{'00': 2049, '01': 2050, '10': 2052, '11': 2041}四个结果的出现次数几乎相等,符合理论上各 25% 的预测。因为你不知道 Alice 会测到哪个贝尔态,所以四种结果等概率出现,但无论出现哪种,Bob 都有对应的恢复策略,所以最终隐形传态的成功率是 100%(理想条件下)。
为了展示保真度,可以提取 Bob 粒子的状态:
psi_target = Statevector.from_label('0') # 或根据 theta/phi 构造 fid = state_fidelity(bob_final_state, psi_target)在无噪声仿真中,保真度是 1.0。如果开启噪声模型,会降到 0.9 左右,这是正常的。可视化工具会把 Bob 恢复前后的布洛赫球画出来,恢复前可能朝任意方向,恢复后和目标方向重合,非常直观。
5. 真实量子硬件实验要点与踩坑记录
5.1 从仿真器切到真实量子设备
当你把配置改成backend.name: ibm并填入自己的 API token 后,DREAMVFIA 会自动从云端拉取可用设备列表。我实测过的设备有ibm_brisbane和ibm_sherbrooke,都是 127 量子比特的超导设备。
第一次跑真机的人通常会犯一个错误:直接用仿真的代码提交作业,也不设置优化级别。结果就是作业排队排到怀疑人生,或者运行时报拓扑映射错误。正确的做法是设置optimization_level: 3,让编译器尽量把电路映射到物理量子比特上时减少 CNOT 门数量。
提交作业后,真机返回结果可能需要几分钟到几十分钟不等,取决于队列长度。建议把shots设到 4096 或者更高,因为真机噪声大,观测次数太少很难得到稳定的统计结果。
5.2 真机上的噪声与保真度损失
真实硬件和仿真器最大的区别就是噪声。超导量子比特的相干时间有限,门操作本身也有误差,测量过程还会引入读出错误。我做过一组对比实验:同样的隐形传态电路,本地仿真保真度 1.0,真机上的保真度大约只有 0.85~0.95。
这不是代码写错了,而是硬件本身的物理限制。CNOT 门的错误率一般在 0.5%~1.5% 左右,而隐形传态电路里恰好需要好几个 CNOT 门,误差会累积。测出来的保真度掉到 0.8 以上已经算不错了。
经验:真机实验不要苛求完美的保真度,重点看趋势。比如你分别传 |0⟩、|1⟩、|+⟩ 三种态,虽然保真度都不到 1,但只要三个态之间的区分度是清晰的,就说明协议在真机上走通了。
5.3 实验前检查清单
我整理了一个真机实验前必须过一遍的检查清单:
- 电路里有没有未使用的量子比特?这会占用真实资源,建议删掉;
- 测量结果对应的经典比特顺序是不是你想的那样?Qiskit 的经典寄存器顺序和直觉相反,特别容易踩坑;
- 有没有设置合理的
optimization_level?建议至少 2 或 3; - shots 够不够?真机上 1024 次太少,4096 起步;
- 配置的物理设备支持当前量子比特数吗?需要查设备的拓扑结构。
把这份清单打印出来贴在显示器旁边,能省掉很多排队浪费的时间。
5.4 一个实测案例
我在ibm_brisbane上跑过一次 theta = π/4、phi = 0 的待传态,总体测量分布接近均匀,四个结果的计数偏差在 5% 以内。Bob 恢复后的状态通过量子态层析测量,算出来的保真度是 0.89。这个结果在真实硬件上属于正常范围,足以证明协议在工程上可行。
那次实验也让我意识到,量子隐形传态并不是什么"黑魔法",它就是一个有明确协议流程的量子信息处理任务。真机上你能清楚地看到统计涨落、设备校准误差这些现实问题,这种"现实感"是仿真器给不了的。
6. 常见问题排查与后续扩展
6.1 高频问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 仿真结果四个计数不均衡 | 待传态参数导致测量概率偏移 | 先换成 |
| 保真度远低于 1 | Bob 的恢复门顺序写反 | 检查 c[0] 和 c[1] 对应的门是否与测量结果匹配 |
| 真机结果波动很大 | 硬件噪声和统计涨落 | 增加 shots,启用编译优化 |
| 作业在队列里一直排队 | 设备负载高或电路编译失败 | 换一个负载低的设备,检查拓扑映射 |
| 输出态的布洛赫球指向错方向 | 待传态的相位参数被忽略 | 确认 u 门的 phi 和 lam 含义与预期一致 |
其中最坑的还是经典比特顺序。Qiskit 里get_counts()返回的 key 是从高到低排列的,比如'01'表示 c[1]=0, c[0]=1,千万别搞反。我在开发 DREAMVFIA 的早期版本时,就因为这个顺序问题调试了一整晚,最后发现恢复门完全用反了。
6.2 保真度计算的细节
量子态保真度定义是两个量子态之间有多接近,公式是 F = |⟨ψ|φ⟩|²。如果你对全套量子态层析不熟,最简单的验证方式是只测 Bob 粒子在某个测量基下的概率分布,然后和理论分布对比。虽然这不是完整保真度,但对于教学实验已经足够说明问题。
DREAMVFIA 里我还内置了一个函数,可以自动根据待传态参数生成理论目标态,再和实际测量结果算保真度。这一步推荐大家在跑任何参数组合时都做一次,能快速发现代码里的低级错误。
6.3 从隐形传态到量子网络
把隐形传态跑通之后,可以往几个方向扩展:
纠缠交换:不用一个纠缠对,而是用两个纠缠对,在中间节点做一次贝尔测量,让两个从未直接作用的粒子产生纠缠。这是量子中继器的核心原理。
量子中继:长距离量子通信中,光子信号会衰减,所以需要中继节点。中继节点不完全解码量子信息,而是通过纠缠交换"接力"纠缠关系,隐形传态在每一段扮演关键角色。
分布式量子计算:把多台小型量子计算机通过隐形传态连接起来,共享量子态,扩展计算规模。这可以理解为把"量子比特"像网络数据包一样在不同机器之间迁移。
这些扩展方向其实都建立在隐形传态的基本面上。把基础吃透,后面的路会顺很多。
6.4 参与 DREAMVFIA 的建议
项目仓库里已经放了CONTRIBUTING.md,欢迎提 issue 和 PR。对初学者来说,最容易上手的贡献方式是补文档、写教程,或者给代码加注释。稍微进阶一点的问题,比如给bell_measure.py增加辅助态验证、给fidelity.py增加更多指标,都是不错的切入点。
开源项目的意义不只是代码本身,更重要的是形成一个互相学习的圈子。你把我写错的逻辑指出来,我帮你优化一个笨拙的实现,大家都是这么进步的。
最后再分享一点个人的体会。我在跑通隐形传态实验之前,一直觉得量子纠缠是个玄学概念,脑子里全是"幽灵""诡异"这类词。但当我一步步把理论推导映射成电路,亲眼看着仿真结果里四种测量结果等概率出现、Bob 恢复后的保真度逼近 1,那个瞬间,纠缠在我心里的形象忽然变得非常具体:它就是一个可以重复操作、可以验证、可以被工程化的物理资源。
现在每当有人问我"量子计算从哪里入门",我都会推荐隐形传态。它既不像 Grover 搜索那样需要先理解一大堆算法背景,也不像量子傅里叶变换那样数学门槛高,它就只需要三件事:一个未知态、一对纠缠粒子、一段经典通信。换句话说,这是一个你可以在一个下午内从零跑通、并且能深刻理解全过程的实验。
如果你也想试一试,我的建议是:不要跳过理论推导直接看代码。先把第 2 章的公式在纸上推一遍,再去读第 4 章的电路,你会发现自己瞬间就明白了每一根连线为什么存在。DREAMVFIA 里所有的实验脚本都带了详细的注释和参考文献,对照着跑一遍,收获绝对比单看代码大一倍。