2. 量子比特与量子门基础
在 Cirq 中,量子程序的最小组成单位不是“线路”,而是量子比特对象与量子门操作。理解这两类对象如何被创建、如何被组合,是后续构建量子线路、模拟与运行实验的前提。本节围绕 Cirq 中最常用的量子比特类型(Qubit、LineQubit、GridQubit)以及基本门(X、Y、Z、H、CNOT)展开,重点说明它们的创建方式、矩阵表示与在电路中的实际用法。
一、量子比特:从抽象 Qubit 到带拓扑的 LineQubit 与 GridQubit
Cirq 中的量子比特是“带标签的对象”,标签本身不携带物理状态,只用于在电路中唯一标识一个比特。最基础的类是 cirq.Qubit,它接受一个可哈希的标签,例如字符串或整数:
import cirq
q0 = cirq.Qubit("q0")
q1 = cirq.Qubit("q1")
print(q0, q1) # q0 q1
这种写法灵活,但缺少“位置”信息。当我们需要在二维网格或一维链上安排比特时,Cirq 提供了两个更具体的子类:
- LineQubit:用整数索引表示一维链上的位置,适合线性排列的量子寄存器。例如
cirq.LineQubit(0)、cirq.LineQubit(1)。 - GridQubit:用
(row, col)表示二维网格坐标,适合超导量子芯片常见的方格拓扑。例如cirq.GridQubit(0, 0)、cirq.GridQubit(0, 1)。
三者的关系可以这样理解:Qubit 是通用基类,LineQubit 与 GridQubit 是带拓扑语义的特化版本。它们都继承自 cirq.Qid,因此可以混用在同一电路中,但实际硬件通常要求使用与芯片拓扑一致的比特类型。下面这张图展示了三种比特的创建方式与拓扑关系:
选择哪种比特类型,取决于目标后端。若只是本地模拟,LineQubit 最简洁;若要对齐 Google 超导芯片的方格拓扑,则应使用 GridQubit,因为两比特门通常只允许作用在相邻的网格比特上。
二、基本门:X、Y、Z、H 与 CNOT 的矩阵表示
Cirq 中的门是“可作用于一个或多个 Qid 的酉操作”。单比特门作用于一个比特,两比特门作用于两个比特。下面给出五个最基础门的矩阵形式(按计算基 |0⟩、|1⟩ 排列):
| 门 | Cirq 写法 | 矩阵 | 作用 |
|---|---|---|---|
| X | cirq.X |
[[0,1],[1,0]] | 比特翻转,|0⟩↔|1⟩ |
| Y | cirq.Y |
[[0,-i],[i,0]] | 比特翻转并带相位 |
| Z | cirq.Z |
[[1,0],[0,-1]] | 相位翻转,|1⟩→−|1⟩ |
| H | cirq.H |
1/√2·[[1,1],[1,-1]] | 生成叠加态 |
| CNOT | cirq.CNOT |
4×4 受控 X 矩阵 | 控制比特为 1 时翻转目标比特 |
在 Cirq 中,门本身是“无比特”的对象,必须通过 on() 或直接调用绑定到具体比特上,才成为可放入电路的操作(Operation)。例如:
q0, q1 = cirq.LineQubit.range(2)
op_x = cirq.X(q0) # X 门作用在 q0
op_h = cirq.H(q1) # H 门作用在 q1
op_cx = cirq.CNOT(q0, q1) # CNOT,q0 控制,q1 目标
print(cirq.unitary(cirq.X)) # 查看 X 的酉矩阵
print(cirq.unitary(cirq.CNOT))
这里有一个容易混淆的点:cirq.X 是门,cirq.X(q0) 是操作。门可以复用,操作则绑定到具体比特。矩阵表示可以通过 cirq.unitary() 直接获取,用于验证门是否符合预期,也便于与教科书中的矩阵对照。
三、把门放进电路:从操作到 Moment 与 Circuit
Cirq 的电路由 Moment 组成,每个 Moment 是一组“可以并行执行、互不冲突”的操作。把操作追加到电路中时,Cirq 会自动安排 Moment:如果两个操作作用于不同比特,它们可以放进同一个 Moment;如果作用于同一比特,则必须分到不同 Moment。
circuit = cirq.Circuit()
circuit.append([cirq.H(q0), cirq.H(q1)]) # 同一 Moment
circuit.append([cirq.CNOT(q0, q1)]) # 下一 Moment
circuit.append([cirq.measure(q0, q1, key='m')])
print(circuit)
运行后会看到类似下面的结构:
0: ───H───@───M('m')───
│ │
1: ───H───X───M────────
其中 @ 表示控制比特,X 表示目标比特,M 表示测量。这个文本图是 Cirq 电路最直观的表示方式,也是调试时最常用的观察手段。若想验证电路是否等价于某个目标酉矩阵,可以用 cirq.unitary(circuit) 获取整体矩阵,再与手算结果比较。
cirq.unitary() 会报错,因为测量不是酉操作。此时应先用 cirq.Circuit(circuit.all_operations()) 去掉测量,或只对酉部分求矩阵。
四、一个可运行的小例子:制备 Bell 态并测量
下面用 H + CNOT 制备 Bell 态 (|00⟩+|11⟩)/√2,并统计测量结果。示例参数为 1000 次采样,属于教学演示,实际运行结果会因随机性略有波动。
import cirq
q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit([
cirq.H(q0),
cirq.CNOT(q0, q1),
cirq.measure(q0, q1, key='result')
])
simulator = cirq.Simulator()
result = simulator.run(circuit, repetitions=1000)
print(result.histogram(key='result'))
预期输出中,0(即 |00⟩)与 3(即 |11⟩)应各占约一半,而 1(|01⟩)与 2(|10⟩)几乎不出现。若出现明显偏离,通常说明 CNOT 的控制/目标顺序写反,或 H 门没有正确作用在控制比特上。这个例子把“比特创建—门作用—电路组装—测量统计”串成了一条完整链路,也是后续更复杂实验的基础模板。
cirq.CNOT(q1, q0) 会得到不同的纠缠方向,虽然 Bell 态本身对称,但在更复杂的电路中会导致逻辑错误。
掌握以上内容后,你已经可以用 Cirq 表达任意由 X、Y、Z、H、CNOT 组成的量子线路,并通过矩阵与测量统计验证其行为。下一阶段将在此基础上引入旋转门、参数化电路与更复杂的多比特门。