3. 单量子比特门操作实战

上一节我们从数学上认识了单量子比特门,本节把这些门真正“跑起来”。目标很明确:在Qiskit中依次构造X、Y、Z、H、S、T以及它们的共轭门,用态矢量模拟器观察每个门作用前后量子态的变化,并通过布洛赫矢量与测量统计验证门的效果是否符合理论预期。本节所有数值均为示例性计算结果,用于说明判断依据,读者在自己的环境中运行会得到一致的结果。

一、搭建最小实验环境

Qiskit从1.x版本起,态矢量模拟由Statevector类承担,电路构建仍使用QuantumCircuit。先准备一个可复用的辅助函数,把任意单比特门作用到初态上并打印态矢量:

from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, Operator
import numpy as np

def apply_and_show(gate_name, gate_method, initial="0"):
    qc = QuantumCircuit(1)
    if initial == "1":
        qc.x(0)                      # 制备 |1>
    qc.barrier()
    getattr(qc, gate_method)(0)      # 施加目标门
    sv = Statevector(qc)
    print(f"{gate_name:>4} on |{initial}> -> {np.round(sv.data, 4)}")
    return sv

这里的关键点是:Statevector(qc)会从全零初态开始演化整条电路,因此若想研究门作用在|1⟩上的效果,必须先用X门制备|1⟩,再用barrier()把制备段与实验段在视觉上分开。这个习惯在后续多比特实验中同样重要。

二、Pauli门:翻转与相位

X门是比特翻转,作用在|0⟩上得到|1⟩,作用在|1⟩上回到|0⟩;Y门同时引入虚数相位,Y|0⟩=i|1⟩;Z门不改变计算基的测量概率,只给|1⟩加上负号。运行下面的调用即可观察:

apply_and_show("X", "x", "0")   # [0.+0.j 1.+0.j]
apply_and_show("Y", "y", "0")   # [0.+0.j 0.+1.j]
apply_and_show("Z", "z", "1")   # [0.+0.j -1.+0.j]

判断依据很直接:态矢量的两个分量就是|0⟩与|1⟩的概率幅。X作用后分量从(1,0)变为(0,1);Y作用后第二分量是纯虚数i,说明存在不可忽略的全局相位——虽然全局相位不可观测,但它会影响后续干涉;Z作用在|1⟩上使第二分量变为−1,测量概率仍是100%的|1⟩,只有通过H门把相位差转成幅度差才能看到。

验证相位类门时,不要只看测量概率。Z、S、T都只改变相对相位,正确做法是在门后接一个H门,把相位信息“翻译”成|0⟩/|1⟩的布居差异,再统计测量结果。

三、Hadamard门:制造叠加

H门把|0⟩变成(|0⟩+|1⟩)/√2,把|1⟩变成(|0⟩−|1⟩)/√2。执行apply_and_show("H", "h", "0"),输出约为[0.7071+0.j 0.7071+0.j],两个分量等幅同相,对应布洛赫球赤道上的+x方向。若对|1⟩施加H,则第二分量为−0.7071,对应−x方向。H门是后续所有“相位转幅度”验证的枢纽,务必先确认它的输出。

四、相位门S、T及其共轭

S门给|1⟩乘上i,T门给|1⟩乘上e^{iπ/4}。它们单独作用在计算基上时测量结果不变,因此必须组合验证。以S门为例,标准验证电路是“H → S → H”:

qc = QuantumCircuit(1)
qc.h(0); qc.s(0); qc.h(0)
print(np.round(Statevector(qc).data, 4))
# 期望 [0.5+0.5j 0.5-0.5j] 附近的结果

更直观的做法是直接读取布洛赫矢量。Qiskit提供Statevector(qc).probabilities()与Operator,但布洛赫坐标可用密度矩阵计算:

from qiskit.quantum_info import DensityMatrix
rho = DensityMatrix(qc)
bx = 2*rho.data[0,1].real
by = 2*rho.data[1,0].imag
bz = (rho.data[0,0] - rho.data[1,1]).real
print(f"Bloch = ({bx:.3f}, {by:.3f}, {bz:.3f})")

对H→S→H电路,理论结果是绕z轴旋转π/2,布洛赫矢量从+x转到+y,即(0,1,0)。若把S换成S†(qc.sdg(0)),则转到−y方向(0,−1,0)。T门对应π/4旋转,H→T→H后布洛赫矢量落在(0.707,0.707,0)附近;T†(qc.tdg(0))则落在(0.707,−0.707,0)。这组对比是判断相位门方向与角度是否正确的核心依据。

单比特门作用效果:态矢量与布洛赫方向对照 态矢量(示例计算结果) 初态 |0⟩ [1.000, 0.000] X |0⟩ [0.000, 1.000] Y |0⟩ [0.000, 0+1i] Z |1⟩ [0.000, −1.000] H |0⟩ [0.707, 0.707] H |1⟩ [0.707, −0.707] H·S·H |0⟩ Bloch (0, 1, 0) H·T·H |0⟩ Bloch (0.707, 0.707, 0) H·T†·H |0⟩ Bloch (0.707, −0.707, 0) 布洛赫球赤道投影(俯视) x y H|0⟩ (+x) H·S·H (+y) H·S†·H (−y) H·T·H H·T†·H 原点

五、用测量统计做交叉验证

态矢量是“上帝视角”,而真实实验只能测量。为了确认相位门效果,可在H→S→H电路末端加测量,并在AerSimulator上跑1024次:

from qiskit import transpile
from qiskit_aer import AerSimulator

qc.measure_all()
sim = AerSimulator()
result = sim.run(transpile(qc, sim), shots=1024).result()
print(result.get_counts())   # 示例:{'0': 512, '1': 512} 附近

H→S→H后态为(0.5+0.5i, 0.5−0.5i),两分量模长相等,因此测量应接近50/50。若把S换成S†,结果同样接近50/50,单看计数无法区分方向——这正是必须借助布洛赫矢量或进一步加相位门的原因。若在H→S→H后再加一个H,则电路等价于S作用在|0⟩上,测量应稳定得到|0⟩;而H→S→H→H→S†→H这类组合可用于构造干涉条纹,验证S与S†互为逆操作。

六、共轭门的实现与核对

Qiskit中S†对应sdg,T†对应tdg,X、Y、Z均为自逆门(X†=X)。核对共轭关系最稳妥的方式是用Operator做矩阵乘法:

from qiskit.quantum_info import Operator
S  = Operator(QuantumCircuit(1).compose(QuantumCircuit(1).s(0)))
Sd = Operator(QuantumCircuit(1).compose(QuantumCircuit(1).sdg(0)))
print(np.allclose((S @ Sd).data, np.eye(2)))   # True

注意compose的顺序:A.compose(B)表示先A后B,与矩阵乘法B·A对应。若顺序写反,会得到看似“不互逆”的错误结论。建议把每个门的2×2矩阵打印出来与理论对照:S=diag(1,i),S†=diag(1,−i),T=diag(1,e^{iπ/4}),T†=diag(1,e^{−iπ/4})。

七、常见偏差与排查

  • 态矢量出现意外全局相位:Y门和T门会引入复数相位,若只比较实部会误判。比较时用np.allclose并允许相位因子,或直接比较布洛赫矢量。
  • Z、S、T“看起来没效果”:它们只改相对相位,必须配合H门或干涉电路观察。
  • 测量计数偏离50/50:先检查是否漏了barrier导致优化器合并门,再确认shots数量足够(建议≥1024)。
  • 共轭门核对失败:优先检查compose顺序与是否误用了qc.s(0)而非sdg。

完成以上步骤后,你应当能够对任意单比特门回答三个问题:它把|0⟩和|1⟩分别映射到什么态矢量;它在布洛赫球上对应哪种旋转;它的逆门是什么、如何用Qiskit实现。这三问构成了后续多比特门与纠缠电路实验的基础。