从经典比特到量子比特:计算观的第一次转折
我们之所以从“比特”讲起,不是因为量子计算只是把经典计算换了个更小的元件,而是因为计算这件事本质上依赖于两类约束:一类是“信息能以什么形式被表示与操作”,另一类是“我们能以什么方式读出结果并确信读到的是我们想要的”。经典比特把这两类约束处理得近乎透明:状态是 0 或 1,读取几乎不影响它,复制也不违背任何原则。量子比特则把这些“透明假设”打碎,让你不得不重新审视:什么叫状态、什么叫读取、什么叫计算的过程。
接下来全书会持续采用一种统一的学习路线:先用尽可能少的物理假设建立可计算的数学模型,再把模型与直觉、实验现象对齐;每引入一个新概念,都会同时给出三种等价表达方式——态矢量(state vector)、矩阵算子(operator)、量子电路(circuit)——并用可运行的模拟实验把抽象变成可观察的统计规律。
计算的基本单位:经典比特为何“好用”
状态、读取与复制:经典世界的默认三件套
一个经典比特(bit)在任意时刻处于两种状态之一:0 或 1。它通常被物理载体承载(电压高低、磁化方向等),但在计算层面我们可以只关心抽象符号 $\{0,1\}$。经典计算之所以工程上可控,背后依赖三个常被忽略的“默认前提”:
1. 可观测性强:读取比特的值可以做到几乎不改变它(例如缓存读、寄存器读,工程上可视为无扰动)。 2. 可复制性强:你可以复制一个比特(或复制一串比特)到任意多份存储中。 3. 状态空间离散且可枚举:单个比特只有两种可能;$n$ 比特有 $2^n$ 种可能,但每一时刻系统确切处于其中之一。
这些前提让经典计算的“语义”非常直接:写入就是把状态设为 0 或 1;读取就是把那个值取出来;复制就是把值再写一遍。程序员很少需要在语言层面考虑“读取会不会改变变量”。
一个小对比:n 比特寄存器与“并行”
当我们说 $n$ 比特可以表示 $2^n$ 种状态时,含义是:它能表示其中一个。例如 3 比特寄存器能表示 0 到 7 的整数,但任一时刻只表示某个确定整数。经典并行计算(多核、多机)是把硬件资源复制多份来同时跑多个分支;并行来自资源叠加,而不是单个寄存器突然“同时处于多个值”。
这一点会直接影响我们理解量子计算时最常见的误解:把量子叠加误读为“同时算完所有答案”。
量子比特:最小物理假设下的三条规则
为了尽量少引入物理细节,我们先把量子比特当作一种新的“信息对象”,它遵循以下三条计算友好的规则(可把它们视为本书的最小公理集)。你不需要先理解电子、自旋或光子,只需要接受:现实允许一种信息对象满足这些规则,并且实验反复验证它们。
规则 1:状态用向量表示(态矢量)
单个量子比特(qubit)的状态用二维复向量表示。我们选定一组基底(通常称为计算基):
- $|0\rangle$
- $|1\rangle$
任意纯态都可写成它们的线性组合: $$ |\psi\rangle = \alpha|0\rangle + \beta|1\rangle, $$ 其中 $\alpha,\beta \in \mathbb{C}$,并满足归一化条件: $$ |\alpha|^2 + |\beta|^2 = 1. $$
这里的 $\alpha,\beta$ 称为振幅(amplitude)。注意:振幅一般是复数;复数的相位将成为量子计算里“可编程干涉”的核心资源。
> 侧边栏(直觉提醒): > 经典比特的“状态空间”是两个离散点 $\{0,1\}$;量子比特的状态空间是一个连续的几何对象(可粗略想象为“带相位的球面”,后续章节会用布洛赫球更精确地表达)。
规则 2:演化用线性变换表示(矩阵算子)
在不测量的情况下,对量子比特施加操作(量子门)对应一个保持归一化的线性变换。用矩阵表示就是: $$ |\psi'\rangle = U|\psi\rangle, $$ 其中 $U$ 是 $2\times 2$ 的复矩阵,并满足幺正性: $$ U^\dagger U = I. $$
幺正性意味着:演化可逆、长度(概率总和)守恒。经典里你可以丢信息(例如与门不可逆),量子演化在更基本层面上是“信息守恒”的,这会影响我们构造算法的方式(例如需要用辅助量子比特与“反算”来清理中间垃圾信息)。
规则 3:测量给出随机结果,并改变状态
当你在计算基 $\{|0\rangle,|1\rangle\}$ 上测量 $|\psi\rangle=\alpha|0\rangle+\beta|1\rangle$ 时:
- 结果为 0 的概率:
$$ P(0)=|\alpha|^2 $$
- 结果为 1 的概率:
$$ P(1)=|\beta|^2 $$
并且测量后状态会坍缩为对应的基态:
- 若得到 0,测量后状态变为 $|0\rangle$
- 若得到 1,测量后状态变为 $|1\rangle$
> 侧边栏(非常关键): > 量子测量不是“读取一个原本就存在的隐藏变量”,更像是用一种方式提问,系统给出随机答案,并在回答后被迫变成与答案一致的状态。因此,测量既是“输出接口”,也是一种会影响后续计算的操作。
这三条规则构成了量子计算最核心的“计算观转折”:状态是向量、演化是幺正线性变换、输出是概率性测量且会扰动状态。
三个根本差异:表示、可观测、可复制
差异 1:信息表示——从离散值到复振幅
经典比特的“状态”就是值;量子比特的“状态”是一个向量。最容易踩坑的是把 $$|\psi\rangle=\alpha|0\rangle+\beta|1\rangle$$ 误读成“以概率 $|\alpha|^2$ 处于 0,以概率 $|\beta|^2$ 处于 1 的随机变量”。这在“只做一次测量”的层面似乎没区别,但在“继续做计算”的层面差别巨大,因为量子态携带的不仅是概率,还携带相位。
例如下面两个态在计算基测量下概率完全一样: $$ |\psi_+\rangle=\frac{|0\rangle+|1\rangle}{\sqrt{2}},\quad |\psi_-\rangle=\frac{|0\rangle-|1\rangle}{\sqrt{2}}. $$ 它们都满足 $P(0)=P(1)=1/2$。但它们在后续经过某些门(例如 Hadamard 门)会产生完全不同的干涉结果:一个会变成确定的 $|0\rangle$,另一个会变成确定的 $|1\rangle$。这正是量子算法能够“把错误答案干涉掉、把正确答案干涉出来”的数学根基。
差异 2:可观测性——读取不可避免地改变被读对象
经典读内存你可以认为是“看一眼不改变内容”。量子态的读取(测量)一般无法做到这种“无扰动”。你当然可以对同一个制备过程重复实验来估计概率分布,但你不能对同一个未知量子态反复测量来同时得到“它在不同基底下的全部信息”。这是量子信息的根本限制之一,也会影响调试方式:量子程序的调试不是逐行打印变量,而更像统计实验与推断。
差异 3:可复制性——未知量子态不可克隆(No-Cloning)
经典信息复制是理所当然的;量子信息中,“复制未知态”在一般情况下是不可能的。我们给出一个非常短但极有力的线性论证,你只需要接受量子演化是线性的(规则 2)。
假设存在一个“通用复制机” $U$,能把任意输入态 $|\psi\rangle$ 复制到一个空白态 $|0\rangle$ 上: $$ U\left(|\psi\rangle|0\rangle\right)=|\psi\rangle|\psi\rangle. $$ 它对基态应当成立: $$ U(|0\rangle|0\rangle)=|0\rangle|0\rangle,\quad U(|1\rangle|0\rangle)=|1\rangle|1\rangle. $$ 但对叠加态 $|+\rangle=\frac{|0\rangle+|1\rangle}{\sqrt{2}}$,由线性性: $$ U(|+\rangle|0\rangle) =U\left(\frac{|0\rangle|0\rangle+|1\rangle|0\rangle}{\sqrt{2}}\right) =\frac{|0\rangle|0\rangle+|1\rangle|1\rangle}{\sqrt{2}}. $$ 而若真能复制,应当得到: $$ |+\rangle|+\rangle =\frac{|0\rangle+|1\rangle}{\sqrt{2}}\otimes\frac{|0\rangle+|1\rangle}{\sqrt{2}} =\frac{|00\rangle+|01\rangle+|10\rangle+|11\rangle}{2}. $$ 这两者不相等,矛盾。因此不存在这样的通用复制机。
> 侧边栏(工程含义): > 你不能“备份”一个未知量子寄存器来做回滚;也不能把某个中间态复制成两份分别做不同分支再合并。量子算法要实现“分支探索”必须走另一条路:把分支写进叠加与纠缠中,再用干涉选择性放大需要的幅度。
叠加不是“随机”,量子计算不是“并行算完所有答案”
误解的来源:把叠加当作“同时拥有两个值”
看到 $$|\psi\rangle=\alpha|0\rangle+\beta|1\rangle$$ 很多人会自然联想到“系统一半是 0,一半是 1”。如果你只关心一次测量的概率,这个类比勉强能用;但一旦你让这个态继续通过量子门,相位与线性叠加会产生干涉,其行为与“经典随机变量”完全不同。
一个最小干涉例子:$H$ 门把不确定变回确定
引入最常用的单比特门之一:Hadamard 门 $H$: $$ H=\frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1\\ 1 & -1 \end{pmatrix}. $$ 它对基态的作用是: $$ H|0\rangle=\frac{|0\rangle+|1\rangle}{\sqrt{2}}=|+\rangle,\quad H|1\rangle=\frac{|0\rangle-|1\rangle}{\sqrt{2}}=|-\rangle. $$
关键现象:连续作用两次 $H$ 会回到原态(因为 $H^2=I$): $$ H(H|0\rangle)=|0\rangle,\quad H(H|1\rangle)=|1\rangle. $$ 如果你把 $H|0\rangle$ 当作“随机得到 0 或 1 的硬币”,那么再做一次 $H$ 不可能把“随机性”消掉并回到确定的 0。现实却是:量子叠加在第二次线性变换下发生干涉,幅度可以相加也可以相消,于是“不确定”可以在适当操作后回到“确定”。
这就是量子算法的核心手段:不是把所有答案并行算完再读取,而是通过构造干涉图样,让错误分支在幅度上相消,让正确分支在幅度上相长,最终把测量概率集中到你要的答案上。
为什么不能“并行读出所有分支”
假设你有一个叠加态,形象地说像“同时走了许多计算路径”。但你最终只能测量一次,测量给出一个经典结果。你无法直接把所有分支的中间信息都读出来:因为一旦你尝试读出“走了哪条路径”,测量本身会破坏相位关系,干涉也就被破坏,算法优势消失。
> 侧边栏(与经典并行的区别一句话版): > 经典并行=复制硬件资源得到多个确定运行;量子“并行感”=同一硬件承载幅度叠加,但输出仍受测量限制,优势来自干涉而非“全读出”。
三种常用表达:态矢量、矩阵算子、量子电路图
同一个量子过程,我们会反复在三种语言之间切换。把它们在这一章就对齐,后面会省下大量认知成本。
1)态矢量:写清“当前是什么态”
在计算基下,我们常用列向量表示: $$ |0\rangle= \begin{pmatrix} 1\\ 0 \end{pmatrix},\quad |1\rangle= \begin{pmatrix} 0\\ 1 \end{pmatrix}. $$ 因此 $$ |\psi\rangle=\alpha|0\rangle+\beta|1\rangle = \begin{pmatrix} \alpha\\ \beta \end{pmatrix}. $$
态矢量适合做:写状态、做推导、算概率。缺点是:当量子比特数变多,维度会指数增长($n$ 比特是 $2^n$ 维),手算会迅速失控。
2)矩阵算子:写清“做了什么操作”
最常见的单比特门(后续会系统扩展):
| 名称 | 符号 | 矩阵 | |---|---|---| | 恒等门 | $I$ | $\begin{pmatrix}1&0\\0&1\end{pmatrix}$ | | 非门 | $X$ | $\begin{pmatrix}0&1\\1&0\end{pmatrix}$ | | 相位翻转 | $Z$ | $\begin{pmatrix}1&0\\0&-1\end{pmatrix}$ | | Hadamard | $H$ | $\frac{1}{\sqrt{2}}\begin{pmatrix}1&1\\1&-1\end{pmatrix}$ |
例如把 $|0\rangle$ 变成 $|1\rangle$: $$ X|0\rangle=|1\rangle. $$
矩阵语言的优势是:组合门就是矩阵相乘,推导清晰;缺点是:在大规模系统中矩阵会极大($2^n\times 2^n$),需要更结构化的表示。
3)量子电路图:写清“顺序与结构”
量子电路把时间从左到右,把量子比特画成水平线,把门画成方块。即使你还没见过多比特纠缠门,单比特电路也能帮助你建立“程序感”。
例如制备 $|+\rangle$ 并测量:
```text |0> ── H ── M ── ```
含义是:初态 $|0\rangle$,经过 $H$ 变成 $|+\rangle$,然后测量 $M$ 得到 0 或 1。
> 侧边栏(阅读建议): > 电路图是“程序的外观”;态矢量和矩阵是“语义的内核”。遇到不理解的电路,不要凭直觉猜测,回到“矩阵作用于态矢量”的定义去算一遍,哪怕只算单比特或少数比特的子结构。
实践主线:用模拟器“看见”概率与统计规律
这一节我们用最轻量的方式做一个“量子实验”:制备 $|0\rangle$、$|1\rangle$、$|+\rangle=(|0\rangle+|1\rangle)/\sqrt{2}$,然后对它们测量很多次,观察频率如何逼近理论概率。
你会得到两种关键直觉: 1. 单次测量是随机的;多次重复呈现稳定分布(大数定律)。 2. 量子态不是“概率表”,因为相位虽然不直接出现在单次测量概率里,但会在后续门操作中影响统计结果(干涉)。
实验流程图(重复试验)
```mermaid graph TD A[选择初态 |0> 或 |1> 或 |+>] --> B[可选: 施加量子门 U] B --> C[在计算基测量] C --> D[记录结果 0/1] D --> E{重复 N 次} E -->|直到 N 次| F[统计频率并对比理论概率] ```
用纯 Python + NumPy 写一个最小模拟器
下面的代码不依赖量子计算框架,目的不是高性能,而是让你看清“态矢量—门—测量”的定义如何落地。
```python import numpy as np
计算基矢量
ket0 = np.array([[1.0], [0.0]], dtype=complex) ket1 = np.array([[0.0], [1.0]], dtype=complex)
常用单比特门
H = (1 / np.sqrt(2)) * np.array([[1, 1], [1, -1]], dtype=complex) X = np.array([[0, 1], [1, 0]], dtype=complex)
def measure_in_z_basis(state, rng=np.random.default_rng()): """ 对单比特态矢量 state 在计算基测量。 返回: (outcome, post_state) """ alpha = state[0, 0] beta = state[1, 0] p0 = abs(alpha) ** 2 r = rng.random() if r < p0: return 0, ket0.copy() else: return 1, ket1.copy()
def run_experiment(state, shots=1000, seed=0): rng = np.random.default_rng(seed) counts = {0: 0, 1: 0} for _ in range(shots): outcome, _ = measure_in_z_basis(state, rng) counts[outcome] += 1 return counts
1) |0> 测量
counts0 = run_experiment(ket0, shots=1000, seed=1)
2) |1> 测量
counts1 = run_experiment(ket1, shots=1000, seed=2)
3) |+> = H|0> 测量
ket_plus = H @ ket0 counts_plus = run_experiment(ket_plus, shots=1000, seed=3)
print("|0>:", counts0) print("|1>:", counts1) print("|+>:", counts_plus) ```
你预期看到的现象(每次随机略有波动):
- $|0\rangle$ 几乎总是测到 0
- $|1\rangle$ 几乎总是测到 1
- $|+\rangle$ 大约一半 0、一半 1
从理论上,$|+\rangle$ 的振幅是 $\alpha=\beta=1/\sqrt{2}$,所以 $$ P(0)=P(1)=\left|\frac{1}{\sqrt{2}}\right|^2=\frac{1}{2}. $$ 当 shots(重复次数)增大时,频率会更接近 $1/2$。
进一步:用一次干涉实验打破“叠加=随机”
我们刚才看到 $|+\rangle$ 测量像抛硬币。但现在做一个关键对照:对 $|+\rangle$ 再施加