Skip to content

量子计算基础 ​

本教程介绍量子计算的基本构建模块:量子比特(qubit)、量子门(quantum gate)和测量(measurement)。你将学习数学基础以及如何在 pyqpanda3 中应用它们。

前置要求: 入门指南 -- 确保 pyqpanda3 已安装并正常工作。


目录 ​


1. 什么是量子比特? ​

1.1 经典比特与量子比特 ​

经典比特(classical bit)可以处于两种状态之一:0 或 1。量子比特(qubit)也有两个基态(basis state),用狄拉克符号(Dirac notation)表示为 |0⟩ 和 |1⟩,但它还可以存在于两者的线性组合中。

属性经典比特量子比特
状态0 或 1|0⟩、|1⟩ 或任意叠加态
符号二进制数字右矢(ket)向量 |ψ⟩
同时状态每次只能处于一种两种同时(叠加)
测量不改变状态坍缩到基态
表示电压电平希尔伯特空间(Hilbert space)中的向量

1.2 叠加态 ​

处于任意态的量子比特可以描述为:

|ψ⟩=α|0⟩+β|1⟩

其中 α 和 β 是复数,称为振幅(amplitude),满足归一化条件(normalization condition):

|α|2+|β|2=1

测量量子比特得到状态 |0⟩ 的概率为 |α|2,测量得到 |1⟩ 的概率为 |β|2。

用列向量形式表示,基态为:

|0⟩=(10),|1⟩=(01)

因此一般量子比特态可以写为:

|ψ⟩=(αβ)

关键洞见在于:量子比特在被测量之前同时持有两种可能性。这不等于"处于未知状态"——振幅 α 和 β 携带了相位信息,使得量子干涉(quantum interference)成为可能。

python
from pyqpanda3 import core

# The |0> state is the default when a qubit is allocated
# Let's verify by measuring a fresh qubit
prog = core.QProg()
prog << core.measure(0, 0)

machine = core.CPUQVM()
machine.run(prog, shots=1000)
counts = machine.result().get_counts()
print(counts)
# Output: {'0': 1000}  -- always |0> since no gates were applied

运行结果:

{'0': 1000}

1.3 布洛赫球 ​

任何单量子比特纯态(pure state)都可以用布洛赫球(Bloch sphere)上的两个角度 θ 和 ϕ 参数化:

|ψ⟩=cos⁡θ2|0⟩+eiϕsin⁡θ2|1⟩

其中 0≤θ≤π 且 0≤ϕ<2π。单位球面上的每个点对应一个唯一的量子比特态。

布洛赫球上的关键点:

  • 北极 (θ=0):|0⟩
  • 南极 (θ=π):|1⟩
  • 正 X 轴 (θ=π/2,ϕ=0):|+⟩=12(|0⟩+|1⟩)
  • 负 X 轴 (θ=π/2,ϕ=π):|−⟩=12(|0⟩−|1⟩)
  • 正 Y 轴 (θ=π/2,ϕ=π/2):|+i⟩=12(|0⟩+i|1⟩)
  • 负 Y 轴 (θ=π/2,ϕ=3π/2):|−i⟩=12(|0⟩−i|1⟩)
mermaid
graph TB
    subgraph "Bloch Sphere Concept"
        B["Bloch Sphere<br/>Unit sphere in 3D"]
        N["North Pole: |0⟩<br/>(θ = 0)"]
        S["South Pole: |1⟩<br/>(θ = π)"]
        PX["+X axis: |+⟩<br/>(θ = π/2, φ = 0)"]
        NX["-X axis: |-⟩<br/>(θ = π/2, φ = π)"]
        PY["+Y axis: |+i⟩<br/>(θ = π/2, φ = π/2)"]
        NY["-Y axis: |-i⟩<br/>(θ = π/2, φ = 3π/2)"]
        P["Any point on surface<br/>represents a pure qubit state"]

        B --- N
        B --- S
        B --- PX
        B --- NX
        B --- PY
        B --- NY
        B --- P
    end

布洛赫向量(Bloch vector) r→=(sin⁡θcos⁡ϕ,sin⁡θsin⁡ϕ,cos⁡θ) 从原点指向球面上的状态。量子门旋转这个向量。

pyqpanda3 通过 visualization 模块提供布洛赫球可视化:

python
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from unittest.mock import patch
# pyqpanda3's bloch_plot module calls plt.switch_backend('TKAgg') at import time,
# which requires an interactive display. We patch it to a no-op since Agg is sufficient.
# Alternatively, set the MPLBACKEND environment variable before running:
#   import os; os.environ['MPLBACKEND'] = 'Agg'
with patch('matplotlib.pyplot.switch_backend'):
    from pyqpanda3.visualization import plot_bloch_vector

# Plot the |+> state (pointing along +X axis)
# Bloch vector: [sin(pi/2)*cos(0), sin(pi/2)*sin(0), cos(pi/2)] = [1, 0, 0]
fig = plot_bloch_vector([1, 0, 0], title="|+> state")
print('Bloch sphere figure created successfully')
print(f'Figure type: {type(fig).__name__}')
plt.close(fig)

运行结果:

Bloch sphere figure created successfully
Figure type: Figure

2. 量子门 ​

2.1 酉变换 ​

量子门是演化量子比特态的酉变换(unitary transformation)。如果矩阵 U 满足以下条件,则称其为酉矩阵(unitary):

U†U=UU†=I

其中 U† 是 U 的共轭转置(conjugate transpose)。这个条件确保:

  • 总概率守恒(|α′|2+|β′|2=1)
  • 门是可逆的(每个门都有逆)

当门 U 作用于态 |ψ⟩ 时,新态为:

|ψ′⟩=U|ψ⟩

对于多量子比特系统,作用于特定量子比特的门通过门矩阵与其他量子比特上的恒等矩阵的张量积(tensor product)来表示。

2.2 单量子比特门 ​

pyqpanda3 提供以下无参数的单量子比特门:

泡利 X 门(NOT 门) ​

X 门翻转计算基态,类似于经典的 NOT 门。

X=(0110)X|0⟩=|1⟩,X|1⟩=|0⟩

在布洛赫球上,X 是绕 X 轴的 π 旋转。

泡利 Y 门 ​

Y=(0−ii0)Y|0⟩=i|1⟩,Y|1⟩=−i|0⟩

在布洛赫球上,Y 是绕 Y 轴的 π 旋转。

泡利 Z 门 ​

Z=(100−1)Z|0⟩=|0⟩,Z|1⟩=−|1⟩

Z 门对 |1⟩ 施加相位翻转。它是绕 Z 轴的 π 旋转。

Hadamard 门(H) ​

Hadamard 门创建等概率叠加(equal superposition):

H=12(111−1)H|0⟩=12(|0⟩+|1⟩)=|+⟩,H|1⟩=12(|0⟩−|1⟩)=|−⟩

这是创建叠加态最常用的门。连续施加两次 H 恢复原始状态:HH=I。

S 门(相位门) ​

S=(100i)=Z1/2S|0⟩=|0⟩,S|1⟩=i|1⟩

S 门是 Z 的平方根。它对 |1⟩ 施加 90∘ 相位。

T 门(π/8 门) ​

T=(100eiπ/4)=S1/2=Z1/4T|0⟩=|0⟩,T|1⟩=eiπ/4|1⟩

T 门是 Z 的四次方根。它是非 Clifford 门,对通用量子计算(universal quantum computation)至关重要。

I 门(恒等门) ​

I=(1001)

恒等门不改变状态。它用于填充线路或作为占位符。

python
from pyqpanda3 import core

# Apply single-qubit gates to qubit 0
prog = core.QProg()
prog << core.H(0)       # Hadamard on qubit 0
prog << core.X(0)       # Pauli-X on qubit 0
prog << core.Y(0)       # Pauli-Y on qubit 0
prog << core.Z(0)       # Pauli-Z on qubit 0
prog << core.S(0)       # S gate on qubit 0
prog << core.T(0)       # T gate on qubit 0
prog << core.I(0)       # Identity on qubit 0

print(prog)

运行结果:

          ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ 
q_0:  |0>─┤H├ ┤X├ ┤Y├ ┤Z├ ┤S├ ┤T├ ┤I├ 
          └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ 
 c :   / ════════════════════════════

无参数单量子比特门总结 ​

门矩阵对 |0⟩ 的效果对 |1⟩ 的效果
X(0110)|1⟩|0⟩
Y(0−ii0)i|1⟩−i|0⟩
Z(100−1)|0⟩−|1⟩
H12(111−1)|+⟩|−⟩
S(100i)|0⟩i|1⟩
T(100eiπ/4)|0⟩eiπ/4|1⟩
I(1001)|0⟩|1⟩

2.3 旋转门 ​

旋转门由角度 θ 参数化,并绕布洛赫球的特定轴旋转状态。

RX 门(绕 X 轴旋转) ​

RX(θ)=(cos⁡θ2−isin⁡θ2−isin⁡θ2cos⁡θ2)=e−iθX/2

RY 门(绕 Y 轴旋转) ​

RY(θ)=(cos⁡θ2−sin⁡θ2sin⁡θ2cos⁡θ2)=e−iθY/2

RZ 门(绕 Z 轴旋转) ​

RZ(θ)=(e−iθ/200eiθ/2)=e−iθZ/2

P 门(相位门) ​

P(θ)=(100eiθ)

注意 P(π/2)=S 且 P(π/4)=T,因此 P 推广了 S 和 T 门。还要注意 P(θ)=RZ(θ) 仅差一个全局相位 e−iθ/2。

python
import math
from pyqpanda3 import core

# Rotation gates take (qubit_index, angle_in_radians)
prog = core.QProg()
prog << core.RX(0, math.pi / 4)    # Rotate pi/4 around X
prog << core.RY(1, math.pi / 2)    # Rotate pi/2 around Y
prog << core.RZ(2, math.pi)        # Rotate pi around Z (= Z gate up to phase)
prog << core.P(0, math.pi / 4)     # Phase gate with angle pi/4 (= T gate)

# Verify that RX(pi) behaves like X (up to global phase)
# RX(pi) = [[0, -i], [-i, 0]] -- multiplies by -i relative to X
prog_rx = core.QProg()
prog_rx << core.RX(0, math.pi)
prog_rx << core.measure(0, 0)

machine = core.CPUQVM()
machine.run(prog_rx, shots=1000)
print(machine.result().get_counts())
# Output: {'1': 1000}  -- same measurement statistics as X|0>

运行结果:

{'1': 1000}

2.4 两量子比特门 ​

两量子比特门作用于一对量子比特,可以创建纠缠(entanglement)——一种独特的量子现象,两个量子比特的状态以经典物理无法描述的方式关联在一起。

CNOT 门(受控非门) ​

最基本的两量子比特门。当且仅当控制量子比特(control qubit)处于 |1⟩ 时,它翻转目标量子比特(target qubit)。

CNOT=(1000010000010010)

基态作用(第一个量子比特是控制,第二个是目标):

|00⟩→|00⟩,|01⟩→|01⟩,|10⟩→|11⟩,|11⟩→|10⟩

在 pyqpanda3 中:core.CNOT(控制, 目标)。

CZ 门(受控 Z 门) ​

当控制量子比特处于 |1⟩ 时,对目标量子比特施加 Z 门。CZ 门是对称的——两个量子比特扮演相同角色。

CZ=(100001000010000−1)|11⟩→−|11⟩,其余不变

在 pyqpanda3 中:core.CZ(量子比特1, 量子比特2)。

SWAP 门 ​

交换两个量子比特的状态。

SWAP=(1000001001000001)|01⟩→|10⟩,|10⟩→|01⟩,|00⟩→|00⟩,|11⟩→|11⟩

在 pyqpanda3 中:core.SWAP(量子比特1, 量子比特2)。

参数化两量子比特门 ​

pyqpanda3 还提供参数化两量子比特门:

门语法描述
CRXcore.CRX(控制, 目标, theta)受控 RX 旋转
CRYcore.CRY(控制, 目标, theta)受控 RY 旋转
CRZcore.CRZ(控制, 目标, theta)受控 RZ 旋转
CPcore.CP(控制, 目标, theta)受控相位
CUcore.CU(控制, 目标, theta, phi, lam, gamma)通用受控酉门
RXXcore.RXX(q1, q2, theta)XX 相互作用
RYYcore.RYY(q1, q2, theta)YY 相互作用
RZZcore.RZZ(q1, q2, theta)ZZ 相互作用
RZXcore.RZX(q1, q2, theta)ZX 相互作用
python
from pyqpanda3 import core

# Two-qubit gate examples
prog = core.QProg()
prog << core.CNOT(0, 1)    # CNOT: control=0, target=1
prog << core.CZ(1, 2)      # CZ between qubits 1 and 2
prog << core.SWAP(0, 1)    # SWAP qubits 0 and 1

# Parameterized two-qubit gates
import math
prog << core.CRX(0, 1, math.pi / 4)   # Controlled-RX with angle pi/4
prog << core.RZZ(0, 1, math.pi / 2)   # ZZ rotation with angle pi/2

print(prog)

运行结果:

          ┌───────────────────┐ 
q_0:  |0>────*── ──── X ────────*─────── ┤0                  ├ 
          ┌──┴─┐      │ ┌───────┴──────┐ │  RZZ(1.57079633)  │ 
q_1:  |0>─┤CNOT├ ──*─ X ┤RX(0.78539816)├ ┤1                  ├ 
          └────┘ ┌─┴┐   └──────────────┘ └───────────────────┘ 
q_2:  |0>─────── ┤CZ├ ─ ──────────────── ───────────────────── 
                 └──┘                                          
 c :   / ═════════════════════════════════════════════════════

2.5 多量子比特门 ​

TOFFOLI 门(CCNOT) ​

TOFFOLI 门是一个三量子比特门,有两个控制量子比特和一个目标量子比特。当且仅当两个控制量子比特都处于 |1⟩ 时,它翻转目标量子比特。

TOFFOLI|a,b,c⟩=|a,b,c⊕(a⋅b)⟩

用矩阵形式(8x8),它除了交换最后两行/列外,其余等同于恒等矩阵:

TOFFOLI=(1000000001000000001000000001000000001000000001000000000100000010)

在 pyqpanda3 中:core.TOFFOLI(控制1, 控制2, 目标)。

python
from pyqpanda3 import core

# TOFFOLI: flips qubit 2 only when qubits 0 and 1 are both |1>
prog = core.QProg()
prog << core.X(0)                  # Set control qubit 0 to |1>
prog << core.X(1)                  # Set control qubit 1 to |1>
prog << core.TOFFOLI(0, 1, 2)     # Target qubit 2 flips to |1>
prog << core.measure([0, 1, 2], [0, 1, 2])

machine = core.CPUQVM()
machine.run(prog, shots=1000)
print(machine.result().get_counts())
# Output: {'111': 1000}  -- all three qubits are |1>

运行结果:

{'111': 1000}

量子门分类 ​

mermaid
graph TD
    QG["Quantum Gates"]
    QG --> SQ["Single-Qubit Gates"]
    QG --> TQ["Two-Qubit Gates"]
    QG --> MQ["Multi-Qubit Gates"]

    SQ --> NP1["Non-Parameterized"]
    SQ --> P1["Parameterized"]

    NP1 --> X["X (NOT)"]
    NP1 --> Y["Y"]
    NP1 --> Z["Z"]
    NP1 --> H["H (Hadamard)"]
    NP1 --> S["S (Phase)"]
    NP1 --> T["T (π/8)"]
    NP1 --> I["I (Identity)"]
    NP1 --> X1["X1"]
    NP1 --> Y1["Y1"]
    NP1 --> Z1["Z1"]

    P1 --> RX["RX(theta)"]
    P1 --> RY["RY(theta)"]
    P1 --> RZ["RZ(theta)"]
    P1 --> P["P(theta)"]
    P1 --> U1["U1(theta)"]
    P1 --> U2["U2(theta, phi)"]
    P1 --> U3["U3(theta, phi, lambda)"]
    P1 --> U4["U4(theta, phi, lambda, gamma)"]
    P1 --> RPHI["RPHI(theta, phi)"]

    TQ --> NP2["Non-Parameterized"]
    TQ --> P2["Parameterized"]

    NP2 --> CNOT["CNOT"]
    NP2 --> CZ["CZ"]
    NP2 --> SWAP["SWAP"]
    NP2 --> ISWAP["ISWAP"]
    NP2 --> SQISWAP["SQISWAP"]
    NP2 --> MS["MS"]

    P2 --> CRX["CRX(theta)"]
    P2 --> CRY["CRY(theta)"]
    P2 --> CRZ["CRZ(theta)"]
    P2 --> CP["CP(theta)"]
    P2 --> CU["CU(theta, phi, lambda, gamma)"]
    P2 --> RXX["RXX(theta)"]
    P2 --> RYY["RYY(theta)"]
    P2 --> RZZ["RZZ(theta)"]
    P2 --> RZX["RZX(theta)"]

    MQ --> TOFFOLI["TOFFOLI (CCNOT)"]

    style QG fill:#e1f5fe
    style SQ fill:#fff3e0
    style TQ fill:#e8f5e9
    style MQ fill:#fce4ec

3. pyqpanda3 中的门操作 ​

pyqpanda3 的门支持四种强大的操作:伴随、受控、幂运算和矩阵提取。这些操作允许你从简单的构建块构造复杂的线路。

3.1 伴随 (.dagger()) ​

.dagger() 方法返回门的伴随(adjoint)(共轭转置)。对于酉门,伴随就是逆。这在以下场景中很有用:

  • 撤销中间结果(反计算)
  • 实现需要逆向步骤的量子算法
  • 构造反射算符
U†=(U∗)T
python
from pyqpanda3 import core
import numpy as np

# The dagger of H is H itself (H is self-adjoint)
h_gate = core.H(0)
h_dagger = h_gate.dagger()

# Verify: H.dagger() matrix should equal H matrix
h_mat = np.array(h_gate.matrix())
hd_mat = np.array(h_dagger.matrix())
print("H == H.dagger():", np.allclose(h_mat, hd_mat))
# Output: H == H.dagger(): True

# Verify: H·H = I (applying H twice returns to original state)
h_h = np.array(h_gate.matrix()) @ np.array(h_gate.matrix())
print("H·H == I:", np.allclose(h_h, np.eye(2)))
# Output: H·H == I: True

# Practical use: apply S then uncompute with S.dagger()
prog = core.QProg()
prog << core.H(0)           # Create superposition |+>
prog << core.S(0)            # Apply S gate
prog << core.S(0).dagger()   # Undo S gate (returns to |+>)
prog << core.H(0)            # Return to |0>
prog << core.measure(0, 0)

machine = core.CPUQVM()
machine.run(prog, shots=1000)
print(machine.result().get_counts())
# Output: {'0': 1000}  -- S and S.dagger() cancel out

运行结果:

H == H.dagger(): True
H·H == I: True
{'0': 1000}

3.2 受控门 (.control()) ​

.control(量子比特) 方法将任何门转换为其受控版本。原始门仅在指定的控制量子比特处于 |1⟩ 态时才作用于其目标量子比特。

这非常强大:你可以创建任何门的受控版本,包括已经有控制的门。

python
from pyqpanda3 import core

# Create a controlled-X (equivalent to CNOT) from X
x_gate = core.X(1)
controlled_x = x_gate.control(0)  # Control on qubit 0

# Use in a circuit
prog = core.QProg()
prog << core.X(0)              # Set control to |1>
prog << controlled_x           # X on qubit 1 is activated
prog << core.measure([0, 1], [0, 1])

machine = core.CPUQVM()
machine.run(prog, shots=1000)
print(machine.result().get_counts())
# Output: {'11': 1000}

# Create a controlled-Hadamard
h_gate = core.H(1)
controlled_h = h_gate.control(0)

# Create a controlled-SWAP (Fredkin gate)
swap_gate = core.SWAP(1, 2)
fredkin = swap_gate.control(0)  # SWAP qubits 1,2 only if qubit 0 is |1>

# Create a doubly-controlled gate (like TOFFOLI from X)
x_gate = core.X(2)
toffoli = x_gate.control(0).control(1)  # X on qubit 2 if qubits 0 AND 1 are |1>

# Verify the doubly-controlled gate
prog2 = core.QProg()
prog2 << core.X(0)             # Set first control to |1>
prog2 << core.X(1)             # Set second control to |1>
prog2 << toffoli                # X on qubit 2 activated
prog2 << core.measure([0, 1, 2], [0, 1, 2])

machine2 = core.CPUQVM()
machine2.run(prog2, shots=1000)
print(machine2.result().get_counts())
# Output: {'111': 1000}

运行结果:

{'11': 1000}
{'111': 1000}

3.3 幂运算 (.power()) ​

.power(k) 方法将门提升到 k 次幂:Uk=U⋅U⋯U(k 次)。对于 k<0,它计算 (U†)|k|。

这对于门的小数幂特别有用:

python
from pyqpanda3 import core
import numpy as np

# X^2 = I (applying NOT twice returns to original)
x_gate = core.X(0)
x_squared = x_gate.power(2)

# Verify: X^2 should equal the identity matrix I
identity = np.eye(2, dtype=complex)
print("X^2 == I:", np.allclose(np.array(x_squared.matrix()), identity))
# Output: X^2 == I: True

# Z^{1/2} = S gate
z_gate = core.Z(0)
z_half = z_gate.power(0.5)

# Verify: Z^{1/2} should match S gate matrix
z_half_mat = np.array(z_half.matrix())
s_mat = np.array(core.S(0).matrix())
print("Z^{1/2} == S:", np.allclose(z_half_mat, s_mat))
# Output: Z^{1/2} == S: True

# Z^{1/4} = T gate
z_quarter = z_gate.power(0.25)
z_quarter_mat = np.array(z_quarter.matrix())
t_mat = np.array(core.T(0).matrix())
print("Z^{1/4} == T:", np.allclose(z_quarter_mat, t_mat))
# Output: Z^{1/4} == T: True

运行结果:

X^2 == I: True
Z^{1/2} == S: True
Z^{1/4} == T: True

3.4 矩阵表示 (.matrix()) ​

.matrix() 方法返回门的酉矩阵作为二维数组。这对于调试、验证和教学目的很有用。

python
from pyqpanda3 import core
import numpy as np

# Get the matrix of any gate
h_matrix = core.H(0).matrix()
print("H matrix:")
print(np.array(h_matrix))
# [[ 0.707  0.707]
#  [ 0.707 -0.707]]

x_matrix = core.X(0).matrix()
print("\nX matrix:")
print(np.array(x_matrix))
# [[0 1]
#  [1 0]]

# Two-qubit gate matrices are 4x4
cnot_matrix = core.CNOT(0, 1).matrix()
print("\nCNOT matrix:")
print(np.array(cnot_matrix))
# [[1 0 0 0]
#  [0 1 0 0]
#  [0 0 0 1]
#  [0 0 1 0]]

# Verify unitarity: U^\dagger U = I
h_arr = np.array(h_matrix)
should_be_identity = h_arr.conj().T @ h_arr
print("\nH^\dagger H (should be I):")
print(np.round(should_be_identity, 10))

# The matrix of a controlled gate
controlled_h = core.H(0).control(2)
ch_matrix = np.array(controlled_h.matrix())
print("\nControlled-H matrix:")
print(np.round(ch_matrix, 3))
# Note: .control().matrix() returns the base gate matrix without
# expanding for control qubits (2x2 for a single-qubit gate).
# [[ 0.707+0.j  0.707+0.j]
#  [ 0.707+0.j -0.707+0.j]]

运行结果:

H 矩阵:
[[ 0.70710678+0.j  0.70710678+0.j]
 [ 0.70710678+0.j -0.70710678+0.j]]

X 矩阵:
[[0.+0.j 1.+0.j]
 [1.+0.j 0.+0.j]]

CNOT 矩阵:
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]]

H^\dagger H (应为 I):
[[1.+0.j 0.+0.j]
 [0.+0.j 1.+0.j]]

受控 H 矩阵:
[[ 0.707+0.j  0.707+0.j]
 [ 0.707+0.j -0.707+0.j]]

4. 测量 ​

4.1 投影测量 ​

测量(measurement)是观测量子态的过程,它将量子态从叠加态坍缩为确定的经典结果。在计算基(computational basis)中,测量处于态 |ψ⟩=α|0⟩+β|1⟩ 的量子比特产生:

  • 结果 0,概率为 |α|2
  • 结果 1,概率为 |β|2

测量后,量子比特处于被测量的基态。这种坍缩是不可逆的——叠加信息已经丢失。

对于处于以下态的 n 量子比特系统:

|ψ⟩=∑i=02n−1ci|i⟩

测量所有量子比特得到比特串(bitstring) |i⟩ 的概率为 |ci|2。

4.2 在 pyqpanda3 中测量 ​

pyqpanda3 提供两种形式的测量:

单量子比特测量:

python
from pyqpanda3 import core

# 语法:core.measure(量子比特索引, 经典比特索引)
# 最小可运行示例:对 qubit 0 施加 H 门后测量
p = core.QProg()
p << core.H(0) << core.measure(0, 0)
m = core.CPUQVM()
m.run(p, shots=100)
print(m.result().get_counts())

运行结果:

{'0': 52, '1': 48}

注意: 量子测量结果是概率性的。上面显示的精确计数是某次运行的示例值。每次运行代码时实际输出都会有所不同。

多量子比特测量:

python
from pyqpanda3 import core

# 语法:core.measure([量子比特_0, 量子比特_1, ...], [经典比特_0, 经典比特_1, ...])
# 最小可运行示例:贝尔态测量
p = core.QProg()
p << core.H(0) << core.CNOT(0, 1)
p << core.measure(0, 0) << core.measure(1, 1)
m = core.CPUQVM()
m.run(p, shots=100)
print(m.result().get_counts())

运行结果:

{'00': 50, '11': 50}

每个量子比特的测量结果存储在对应的经典比特(cbit)中。

python
from pyqpanda3 import core

# Single qubit measurement
prog1 = core.QProg()
prog1 << core.H(0)                 # Create superposition
prog1 << core.measure(0, 0)        # Measure qubit 0 into cbit 0

machine = core.CPUQVM()
machine.run(prog1, shots=1000)
print("Single qubit:", machine.result().get_counts())
# Output: {'0': 498, '1': 502}

# Multi-qubit measurement
prog2 = core.QProg()
prog2 << core.H(0)                 # Superposition on qubit 0
prog2 << core.X(1)                 # Qubit 1 in |1>
prog2 << core.measure([0, 1], [0, 1])  # Measure both

machine.run(prog2, shots=1000)
print("Two qubits:", machine.result().get_counts())
# Output: {'10': ~500, '11': ~500}
# Qubit 0 is random, qubit 1 is always 1

运行结果:

单量子比特: {'0': 528, '1': 472}
两量子比特: {'10': 503, '11': 497}

4.3 基于采样的测量 ​

量子测量本质上是概率性的。为了积累统计信息,我们多次运行同一线路(称为"采样(shots)")。大数定律保证随着采样次数增加,观测频率收敛到真实概率。

python
from pyqpanda3 import core

# Demonstrate shot-based measurement convergence
prog = core.QProg()
prog << core.H(0)       # Creates |+> = (|0> + |1>)/sqrt(2)
prog << core.measure(0, 0)

machine = core.CPUQVM()

# Few shots: high variance
machine.run(prog, shots=10)
counts_10 = machine.result().get_counts()
print(f"10 shots:   {counts_10}")

# Moderate shots
machine.run(prog, shots=100)
counts_100 = machine.result().get_counts()
print(f"100 shots:  {counts_100}")

# Many shots: closer to 50/50
machine.run(prog, shots=10000)
counts_10000 = machine.result().get_counts()
print(f"10000 shots: {counts_10000}")

# The probabilities approach 0.5 for each outcome
total = sum(counts_10000.values())
for key, val in sorted(counts_10000.items()):
    print(f"  P({key}) = {val/total:.4f}")

运行结果:

10 次采样:   {'0': 7, '1': 3}
100 次采样:  {'0': 49, '1': 51}
10000 次采样: {'0': 5132, '1': 4868}
  P(0) = 0.5132
  P(1) = 0.4868

下图说明了测量过程:

mermaid
flowchart TD
    A["Quantum Circuit"] --> B["Run on Simulator<br/>shots=N"]
    B --> C["Execute N times"]

    C --> D["Shot 1:<br/>collapse to |0> or |1>"]
    C --> E["Shot 2:<br/>collapse to |0> or |1>"]
    C --> F["Shot ..."]
    C --> G["Shot N:<br/>collapse to |0> or |1>"]

    D --> H["Aggregate Results<br/>get_counts()"]
    E --> H
    F --> H
    G --> H

    H --> I["Output: dict<br/>{'0': 498, '1': 502}"]

    style A fill:#e1f5fe
    style B fill:#fff3e0
    style H fill:#e8f5e9
    style I fill:#fce4ec

4.4 完整示例:贝尔态 ​

让我们将所有内容组合起来创建贝尔态(Bell State)——最简单的纠缠态之一:

|Φ+⟩=12(|00⟩+|11⟩)

线路为:量子比特 0 上的 H,然后是以 0 为控制、1 为目标的 CNOT。

python
from pyqpanda3 import core

# Step 1: Build the Bell state circuit
prog = core.QProg()
prog << core.H(0)                    # Hadamard creates superposition on qubit 0
prog << core.CNOT(0, 1)              # Entangle qubits 0 and 1
prog << core.measure([0, 1], [0, 1]) # Measure both qubits

# Step 2: Run on the CPU simulator
machine = core.CPUQVM()
machine.run(prog, shots=10000)

# Step 3: Get the measurement results
counts = machine.result().get_counts()
print("Bell state results:")
print(counts)
# Expected output: {'00': ~5000, '11': ~5000}
# Note: '01' and '10' should not appear (or very rarely due to numerical precision)

# Step 4: Analyze the results
total = sum(counts.values())
for bitstring in ['00', '01', '10', '11']:
    count = counts.get(bitstring, 0)
    probability = count / total
    print(f"  |{bitstring}>: {count} counts ({probability:.4f})")

运行结果:

贝尔态结果:
{'00': 5119, '11': 4881}
  |00>: 5119 次计数 (0.5119)
  |01>: 0 次计数 (0.0000)
  |10>: 0 次计数 (0.0000)
  |11>: 4881 次计数 (0.4881)

为什么只有 00 和 11? H 门将量子比特 0 置于 |+⟩=12(|0⟩+|1⟩) 态。CNOT 将量子比特 0 的状态复制到量子比特 1:

CNOT(H|0⟩⊗|0⟩)=12(|00⟩+|11⟩)

两个量子比特现在纠缠了:测量一个立即确定另一个,无论它们之间的物理距离多远。这是量子隐形传态(quantum teleportation)、超密编码(superdense coding)和量子纠错(quantum error correction)的资源。


5. 总结 ​

本教程涵盖了量子计算的三个基础概念:

概念核心思想pyqpanda3 API
量子比特|0⟩ 和 |1⟩ 的叠加分配时的默认状态
量子门量子比特态的酉变换core.H(0)、core.X(0)、core.CNOT(0,1) 等
测量将叠加态坍缩为经典比特core.measure(量子比特, 经典比特)

门操作扩展了门库:

操作方法描述
伴随.dagger()返回逆门 U†
受控.control(量子比特)添加控制量子比特
幂运算.power(k)计算 Uk(支持小数 k)
矩阵.matrix()返回酉矩阵

下一步:


快速参考 ​

python
from pyqpanda3 import core
import math

# ===================
# Single-Qubit Gates
# ===================
core.H(0)           # Hadamard
core.X(0)           # Pauli-X (NOT)
core.Y(0)           # Pauli-Y
core.Z(0)           # Pauli-Z
core.S(0)           # S gate (sqrt of Z)
core.T(0)           # T gate (4th root of Z)
core.I(0)           # Identity

# ===================
# Rotation Gates
# ===================
core.RX(0, math.pi / 4)   # Rotate around X
core.RY(0, math.pi / 2)   # Rotate around Y
core.RZ(0, math.pi)       # Rotate around Z
core.P(0, math.pi / 4)    # Phase gate

# ===================
# Two-Qubit Gates
# ===================
core.CNOT(0, 1)            # Controlled-NOT
core.CZ(0, 1)              # Controlled-Z
core.SWAP(0, 1)            # SWAP

# ===================
# Multi-Qubit Gates
# ===================
core.TOFFOLI(0, 1, 2)     # Doubly-controlled NOT

# ===================
# Gate Operations
# ===================
gate = core.H(0)
gate.dagger()               # Adjoint (inverse)
gate.control(2)             # Controlled version (control on qubit 2)
gate.power(0.5)             # Fractional power
gate.matrix()               # Unitary matrix

# ===================
# Measurement
# ===================
core.measure(0, 0)                       # Single qubit
core.measure([0, 1], [0, 1])             # Multiple qubits

# ===================
# Run Circuit
# ===================
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])

machine = core.CPUQVM()
machine.run(prog, shots=1000)
counts = machine.result().get_counts()
print(counts)

运行结果:

{'00': 506, '11': 494}

知识检查 ​

测试你对使用 pyqpanda3 的量子计算基础的理解。

Q1: 量子比特态 |ψ⟩=α|0⟩+β|1⟩ 的归一化约束是什么?

A1: 振幅必须满足 |α|2+|β|2=1。这确保所有测量结果的总概率等于 1,这是量子力学的基本要求。

Q2: Hadamard 门对基态 |0⟩ 和 |1⟩ 的作用是什么?

A2: H|0⟩=12(|0⟩+|1⟩)=|+⟩ 且 H|1⟩=12(|0⟩−|1⟩)=|−⟩。它从计算基态创建等概率叠加,在 Z 基和 X 基之间映射。

Q3: 阐述玻恩法则(Born rule)。如果量子比特处于态 |ψ⟩=12|0⟩+32|1⟩,测量概率是多少?

A3: 玻恩法则指出 P(x)=|αx|2。这里,P(0)=|1/2|2=1/4,P(1)=|3/2|2=3/4。

Q4: 可分态(product state)与纠缠态(entangled state)有什么区别?

A4: 可分态可以分解为 |ψ⟩=|ϕ1⟩⊗|ϕ2⟩,意味着每个量子比特有独立的状态。纠缠态无法分解——量子比特展现出无法用独立状态描述的关联。贝尔态 |Φ+⟩=12(|00⟩+|11⟩) 是纠缠态。

Q5: S 门、T 门和 Z 门之间有什么关系?

A5: S2=Z 且 T2=S,因此 T4=S2=Z 且 T8=I。S 门是 Z 的平方根,T 门是 Z 的四次方根。

Q6: 写出 RX(π/2) 的矩阵并解释它对 |0⟩ 的作用。

A6: RX(θ)=(cos⁡(θ/2)−isin⁡(θ/2)−isin⁡(θ/2)cos⁡(θ/2))。对于 θ=π/2:RX(π/2)=12(1−i−i1)。作用于 |0⟩ 时,产生 12(|0⟩−i|1⟩),即布洛赫球上的 |−i⟩ 本征态。

Q7: 结合连续施加两个 Hadamard 门的场景,解释量子干涉(quantum interference)。

A7: HH|0⟩=|0⟩ 且 HH|1⟩=|1⟩。第一个 H 创建 12(|0⟩+|1⟩),然后第二个 H 产生 12(|0⟩+|1⟩+|0⟩−|1⟩)=|0⟩。|1⟩ 的振幅相消(相消干涉(destructive interference)),而 |0⟩ 的振幅相加(相长干涉(constructive interference))。


练习 1:态制备

编写一个 pyqpanda3 程序,制备态 |ψ⟩=cos⁡(π/6)|0⟩+sin⁡(π/6)|1⟩。验证测量概率符合玻恩法则预测:P(0)=cos2⁡(π/6)=3/4 且 P(1)=sin2⁡(π/6)=1/4。

解答:

python
import numpy as np
from pyqpanda3 import core

qvm = core.CPUQVM()

# The state cos(θ/2)|0⟩ + sin(θ/2)|1⟩ is prepared by RY(θ)
# We want cos(π/6)|0⟩ + sin(π/6)|1⟩
# So θ/2 = π/6 → θ = π/3
theta = np.pi / 3

prog = core.QProg()
prog << core.RY(0, theta)
prog << core.measure([0], [0])

qvm.run(prog, shots=10000)
result = qvm.result()
counts = result.get_counts()

p0_measured = counts.get("0", 0) / 10000
p1_measured = counts.get("1", 0) / 10000
p0_expected = np.cos(np.pi/6)**2  # 0.75
p1_expected = np.sin(np.pi/6)**2  # 0.25

print(f"P(|0⟩) measured: {p0_measured:.4f}, expected: {p0_expected:.4f}")
print(f"P(|1⟩) measured: {p1_measured:.4f}, expected: {p1_expected:.4f}")
assert abs(p0_measured - p0_expected) < 0.03
assert abs(p1_measured - p1_expected) < 0.03
print("Verification passed!")

运行结果:

P(|0⟩) 测量值: 0.7538, 期望值: 0.7500
P(|1⟩) 测量值: 0.2462, 期望值: 0.2500
验证通过!

练习 2:纠缠验证

制备所有四个贝尔态并验证其测量统计。四个贝尔态为:

|Φ+⟩=12(|00⟩+|11⟩),|Φ−⟩=12(|00⟩−|11⟩)|Ψ+⟩=12(|01⟩+|10⟩),|Ψ−⟩=12(|01⟩−|10⟩)

解答:

python
from pyqpanda3 import core

qvm = core.CPUQVM()
shots = 5000

def run_and_print(name, prog):
    prog << core.measure([0, 1], [0, 1])
    qvm.run(prog, shots=shots)
    counts = qvm.result().get_counts()
    print(f"{name}: {counts}")
    return counts

# |Φ+⟩ = (|00⟩ + |11⟩) / √2
prog_pp = core.QProg()
prog_pp << core.H(0) << core.CNOT(0, 1)
c1 = run_and_print("|Φ+⟩", prog_pp)
assert c1.get("01", 0) < 100 and c1.get("10", 0) < 100

# |Φ-⟩ = (|00⟩ - |11⟩) / √2
prog_pm = core.QProg()
prog_pm << core.H(0) << core.Z(0) << core.CNOT(0, 1)
c2 = run_and_print("|Φ-⟩", prog_pm)
assert c2.get("01", 0) < 100 and c2.get("10", 0) < 100

# |Ψ+⟩ = (|01⟩ + |10⟩) / √2
prog_mp = core.QProg()
prog_mp << core.H(0) << core.X(1) << core.CNOT(0, 1)
c3 = run_and_print("|Ψ+⟩", prog_mp)
assert c3.get("00", 0) < 100 and c3.get("11", 0) < 100

# |Ψ-⟩ = (|01⟩ - |10⟩) / √2
prog_mm = core.QProg()
prog_mm << core.X(0) << core.H(0) << core.X(1) << core.CNOT(0, 1)
c4 = run_and_print("|Ψ-⟩", prog_mm)
assert c4.get("00", 0) < 100 and c4.get("11", 0) < 100

print("\nAll four Bell states verified!")

运行结果:

|Φ+⟩: {'00': 2429, '11': 2571}
|Φ-⟩: {'00': 2437, '11': 2563}
|Ψ+⟩: {'01': 2456, '10': 2544}
|Ψ-⟩: {'01': 2437, '10': 2563}

所有四个贝尔态验证完成!

练习 3:自定义门矩阵验证

从 2×2 矩阵创建自定义酉门,并验证其对基态的作用是否符合预期的矩阵乘法。

解答:

python
import numpy as np
from pyqpanda3 import core

# Define a custom unitary: RY(π/4) matrix
theta = np.pi / 4
matrix = np.array([
    [np.cos(theta/2), -np.sin(theta/2)],
    [np.sin(theta/2),  np.cos(theta/2)]
], dtype=complex)

# Create oracle from matrix and verify
qvm = core.CPUQVM()

# Apply to |0⟩: expect cos(π/8)|0⟩ + sin(π/8)|1⟩
prog = core.QProg()
oracle = core.Oracle([0], matrix)
prog << oracle << core.measure([0], [0])
qvm.run(prog, shots=10000)
counts = qvm.result().get_counts()
p0 = counts.get("0", 0) / 10000
expected_p0 = np.cos(np.pi/8)**2
print(f"P(|0⟩) measured: {p0:.4f}, expected: {expected_p0:.4f}")
assert abs(p0 - expected_p0) < 0.03
print("Custom gate verified!")

运行结果:

P(|0⟩) 测量值: 0.8547, 期望值: 0.8536
自定义门验证通过!

Released under the MIT License.