量子计算基础
本教程介绍量子计算的基本构建模块:量子比特(qubit)、量子门(quantum gate)和测量(measurement)。你将学习数学基础以及如何在 pyqpanda3 中应用它们。
前置要求: 入门指南 -- 确保 pyqpanda3 已安装并正常工作。
目录
1. 什么是量子比特?
1.1 经典比特与量子比特
经典比特(classical bit)可以处于两种状态之一:0 或 1。量子比特(qubit)也有两个基态(basis state),用狄拉克符号(Dirac notation)表示为
| 属性 | 经典比特 | 量子比特 |
|---|---|---|
| 状态 | 0 或 1 | |
| 符号 | 二进制数字 | 右矢(ket)向量 |
| 同时状态 | 每次只能处于一种 | 两种同时(叠加) |
| 测量 | 不改变状态 | 坍缩到基态 |
| 表示 | 电压电平 | 希尔伯特空间(Hilbert space)中的向量 |
1.2 叠加态
处于任意态的量子比特可以描述为:
其中
测量量子比特得到状态
用列向量形式表示,基态为:
因此一般量子比特态可以写为:
关键洞见在于:量子比特在被测量之前同时持有两种可能性。这不等于"处于未知状态"——振幅
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)上的两个角度
其中
布洛赫球上的关键点:
- 北极 (
): - 南极 (
): - 正 X 轴 (
): - 负 X 轴 (
): - 正 Y 轴 (
): - 负 Y 轴 (
):
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)
pyqpanda3 通过 visualization 模块提供布洛赫球可视化:
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: Figure2. 量子门
2.1 酉变换
量子门是演化量子比特态的酉变换(unitary transformation)。如果矩阵
其中
- 总概率守恒(
) - 门是可逆的(每个门都有逆)
当门
对于多量子比特系统,作用于特定量子比特的门通过门矩阵与其他量子比特上的恒等矩阵的张量积(tensor product)来表示。
2.2 单量子比特门
pyqpanda3 提供以下无参数的单量子比特门:
泡利 X 门(NOT 门)
X 门翻转计算基态,类似于经典的 NOT 门。
在布洛赫球上,X 是绕 X 轴的
泡利 Y 门
在布洛赫球上,Y 是绕 Y 轴的
泡利 Z 门
Z 门对
Hadamard 门(H)
Hadamard 门创建等概率叠加(equal superposition):
这是创建叠加态最常用的门。连续施加两次 H 恢复原始状态:
S 门(相位门)
S 门是 Z 的平方根。它对
T 门( 门)
T 门是 Z 的四次方根。它是非 Clifford 门,对通用量子计算(universal quantum computation)至关重要。
I 门(恒等门)
恒等门不改变状态。它用于填充线路或作为占位符。
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 : / ════════════════════════════无参数单量子比特门总结
| 门 | 矩阵 | 对 | 对 |
|---|---|---|---|
| X | |||
| Y | |||
| Z | |||
| H | |||
| S | |||
| T | |||
| I |
2.3 旋转门
旋转门由角度
RX 门(绕 X 轴旋转)
RY 门(绕 Y 轴旋转)
RZ 门(绕 Z 轴旋转)
P 门(相位门)
注意
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)处于
基态作用(第一个量子比特是控制,第二个是目标):
在 pyqpanda3 中:core.CNOT(控制, 目标)。
CZ 门(受控 Z 门)
当控制量子比特处于
在 pyqpanda3 中:core.CZ(量子比特1, 量子比特2)。
SWAP 门
交换两个量子比特的状态。
在 pyqpanda3 中:core.SWAP(量子比特1, 量子比特2)。
参数化两量子比特门
pyqpanda3 还提供参数化两量子比特门:
| 门 | 语法 | 描述 |
|---|---|---|
| CRX | core.CRX(控制, 目标, theta) | 受控 RX 旋转 |
| CRY | core.CRY(控制, 目标, theta) | 受控 RY 旋转 |
| CRZ | core.CRZ(控制, 目标, theta) | 受控 RZ 旋转 |
| CP | core.CP(控制, 目标, theta) | 受控相位 |
| CU | core.CU(控制, 目标, theta, phi, lam, gamma) | 通用受控酉门 |
| RXX | core.RXX(q1, q2, theta) | XX 相互作用 |
| RYY | core.RYY(q1, q2, theta) | YY 相互作用 |
| RZZ | core.RZZ(q1, q2, theta) | ZZ 相互作用 |
| RZX | core.RZX(q1, q2, theta) | ZX 相互作用 |
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 门是一个三量子比特门,有两个控制量子比特和一个目标量子比特。当且仅当两个控制量子比特都处于
用矩阵形式(8x8),它除了交换最后两行/列外,其余等同于恒等矩阵:
在 pyqpanda3 中:core.TOFFOLI(控制1, 控制2, 目标)。
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}量子门分类
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:#fce4ec3. pyqpanda3 中的门操作
pyqpanda3 的门支持四种强大的操作:伴随、受控、幂运算和矩阵提取。这些操作允许你从简单的构建块构造复杂的线路。
3.1 伴随 (.dagger())
.dagger() 方法返回门的伴随(adjoint)(共轭转置)。对于酉门,伴随就是逆。这在以下场景中很有用:
- 撤销中间结果(反计算)
- 实现需要逆向步骤的量子算法
- 构造反射算符
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(量子比特) 方法将任何门转换为其受控版本。原始门仅在指定的控制量子比特处于
这非常强大:你可以创建任何门的受控版本,包括已经有控制的门。
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 次幂:
这对于门的小数幂特别有用:
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: True3.4 矩阵表示 (.matrix())
.matrix() 方法返回门的酉矩阵作为二维数组。这对于调试、验证和教学目的很有用。
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,概率为
测量后,量子比特处于被测量的基态。这种坍缩是不可逆的——叠加信息已经丢失。
对于处于以下态的
测量所有量子比特得到比特串(bitstring)
4.2 在 pyqpanda3 中测量
pyqpanda3 提供两种形式的测量:
单量子比特测量:
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}注意: 量子测量结果是概率性的。上面显示的精确计数是某次运行的示例值。每次运行代码时实际输出都会有所不同。
多量子比特测量:
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)中。
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)")。大数定律保证随着采样次数增加,观测频率收敛到真实概率。
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下图说明了测量过程:
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:#fce4ec4.4 完整示例:贝尔态
让我们将所有内容组合起来创建贝尔态(Bell State)——最简单的纠缠态之一:
线路为:量子比特 0 上的 H,然后是以 0 为控制、1 为目标的 CNOT。
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 置于
两个量子比特现在纠缠了:测量一个立即确定另一个,无论它们之间的物理距离多远。这是量子隐形传态(quantum teleportation)、超密编码(superdense coding)和量子纠错(quantum error correction)的资源。
5. 总结
本教程涵盖了量子计算的三个基础概念:
| 概念 | 核心思想 | pyqpanda3 API |
|---|---|---|
| 量子比特 | 分配时的默认状态 | |
| 量子门 | 量子比特态的酉变换 | core.H(0)、core.X(0)、core.CNOT(0,1) 等 |
| 测量 | 将叠加态坍缩为经典比特 | core.measure(量子比特, 经典比特) |
门操作扩展了门库:
| 操作 | 方法 | 描述 |
|---|---|---|
| 伴随 | .dagger() | 返回逆门 |
| 受控 | .control(量子比特) | 添加控制量子比特 |
| 幂运算 | .power(k) | 计算 |
| 矩阵 | .matrix() | 返回酉矩阵 |
下一步:
- 线路构建 -- 学习如何使用
QProg、QCircuit和<<运算符将门组合成复杂线路 - 模拟 -- 探索不同的模拟器(CPUQVM、DensityMatrixSimulator、Stabilizer)
- 可视化 -- 学习绘制线路和在布洛赫球上绘制量子态
快速参考
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: 量子比特态
A1: 振幅必须满足
Q2: Hadamard 门对基态
A2:
Q3: 阐述玻恩法则(Born rule)。如果量子比特处于态
A3: 玻恩法则指出
Q4: 可分态(product state)与纠缠态(entangled state)有什么区别?
A4: 可分态可以分解为
Q5: S 门、T 门和 Z 门之间有什么关系?
A5:
Q6: 写出
A6:
Q7: 结合连续施加两个 Hadamard 门的场景,解释量子干涉(quantum interference)。
A7:
练习 1:态制备
编写一个 pyqpanda3 程序,制备态
解答:
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:纠缠验证
制备所有四个贝尔态并验证其测量统计。四个贝尔态为:
解答:
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:自定义门矩阵验证
从
解答:
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
自定义门验证通过!