噪声模拟
真实量子硬件存在噪声。本教程介绍如何使用 NoiseModel 框架和七种内置量子误差通道,在 pyqpanda3 中建模和模拟噪声。
为什么噪声模拟很重要
量子计算机运行在 NISQ(含噪中等规模量子)时代,硬件受到各种噪声源的影响:
- 门误差:不完美的门实现
- 读出误差:测量错误地报告结果
- 退相干:量子比特随时间丢失量子信息(T1 弛豫、T2 退相位)
噪声模拟可以帮助你:
- 预测算法在真实硬件上的表现
- 开发抗噪声算法
- 表征和校准量子设备
- 验证纠错方案
噪声模型框架
NoiseModel 类
NoiseModel 类将量子误差和读出误差收集到一个统一的模型中,可以传递给任何模拟器:
from pyqpanda3 import core
# Create an empty noise model
noise = core.NoiseModel()
# Check if any noise is configured
print(f"Noise enabled: {noise.is_enabled()}")
# Output: Noise enabled: False添加门误差
为特定的门和量子比特添加量子误差:
from pyqpanda3 import core
# Add error to a specific gate type on specific qubits
error = core.depolarizing_error(0.01)
noise.add_quantum_error(error, core.GateType.CNOT, [0, 1])
# Add error to multiple gate types on specific qubits
noise.add_quantum_error(error, [core.GateType.H, core.GateType.T], [0])
# Add error to a gate type on ALL qubits
noise.add_all_qubit_quantum_error(error, core.GateType.CNOT)
# Add error to multiple gate types on ALL qubits
noise.add_all_qubit_quantum_error(error, [core.GateType.H, core.GateType.CNOT])添加读出误差
读出误差建模测量到错误经典值的概率:
from pyqpanda3 import core
# Add readout error to a specific qubit
# probs[i][j] = P(measuring j | true state is i)
noise.add_read_out_error([[0.95, 0.05], [0.05, 0.95]], 0)
# Add readout error to ALL qubits
noise.add_all_qubit_read_out_error([[0.95, 0.05], [0.05, 0.95]])量子误差通道
pyqpanda3 提供七种量子误差通道,每种建模不同的物理噪声机制。所有误差通道均使用 Kraus 算子描述。
Kraus 表示
每个量子噪声通道都可以用一组 Kraus 算子
其中
1. Pauli X 误差(比特翻转)
比特翻转通道以概率
Kraus 算子:
from pyqpanda3 import core
# Create a bit flip error with probability 0.05
error_x = core.pauli_x_error(0.05)物理模型:能量弛豫导致
2. Pauli Y 误差
Pauli Y 误差以概率
Kraus 算子:
from pyqpanda3 import core
# Create a Pauli Y error with probability 0.03
error_y = core.pauli_y_error(0.03)3. Pauli Z 误差(相位翻转)
相位翻转通道以概率
Kraus 算子:
from pyqpanda3 import core
# Create a phase flip error with probability 0.02
error_z = core.pauli_z_error(0.02)物理模型:退相位在
4. 去极化误差
去极化通道以概率
对于单量子比特(
Kraus 算子:
from pyqpanda3 import core
# Create a depolarizing error with probability 0.01
error_dep = core.depolarizing_error(0.01)物理模型:将态驱向最大熵的通用噪声
5. 振幅阻尼误差
振幅阻尼通道建模 T1 弛豫(能量耗散)。它描述了
Kraus 算子:
from pyqpanda3 import core
# Create an amplitude damping error with decay rate 0.02
error_ad = core.amplitude_damping_error(0.02)物理模型:T1 弛豫——量子比特向环境损失能量
6. 相位阻尼误差
相位阻尼通道建模 T2 退相位(相位相干性的丧失):
Kraus 算子:
from pyqpanda3 import core
# Create a phase damping error with rate 0.01
error_pd = core.phase_damping_error(0.01)物理模型:T2 退相位——无能量损失情况下量子相位信息的丢失
7. 退相干误差
退相干误差结合了振幅阻尼和相位阻尼,同时建模 T1 和 T2 过程:
from pyqpanda3 import core
# Create a decoherence error (T1=80us, T2=60us, gate_time=20ns)
error_dec = core.decoherence_error(80.0, 60.0, 20.0)物理模型:T1 和 T2 退相干过程的综合
误差通道汇总
| 误差 | 物理模型 | Kraus 算子 | 参数 |
|---|---|---|---|
pauli_x_error(p) | 比特翻转 | ||
pauli_y_error(p) | 比特+相位翻转 | ||
pauli_z_error(p) | 相位翻转 | ||
depolarizing_error(p) | 通用噪声 | 4 个算子 | |
amplitude_damping_error(γ) | T1 衰减 | 2 个算子 | |
phase_damping_error(λ) | T2 退相位 | 2 个算子 | |
decoherence_error(T1, T2, t_gate) | T1+T2 综合 | 多个算子 | T1、T2(μs)、t_gate(ns) |
QuantumError 类
QuantumError 类封装噪声数据并提供组合操作:
创建量子误差
from pyqpanda3 import core
import numpy as np
# Method 1: From Kraus matrices (list of numpy arrays)
kraus = [
np.sqrt(0.99) * np.eye(2),
np.sqrt(0.01) * np.array([[0, 1], [1, 0]])
]
error = core.QuantumError(kraus)
# Method 2: From noise map (Pauli probabilities)
noise_map = {"X": 0.01, "Y": 0.005, "Z": 0.005}
error2 = core.QuantumError(noise_map)误差属性
from pyqpanda3 import core
# Get number of qubits affected
print(f"Qubits affected: {error.qubit_num()}")
# Get the error type
print(f"Error type: {error.error_type()}")
# Get Kraus matrices
karus = error.error_karus()
print(f"Kraus matrices: {karus}")误差组合
from pyqpanda3 import core
# Tensor product of two errors (independent errors on different qubits)
combined = error.tensor(error2)
# Expansion to a larger system
expanded = error.expand(error2)
# Sequential composition (error applied after another)
composed = error.compose(error2)比较噪声通道
不同的噪声通道以根本不同的方式影响量子态。理解这些差异对于为你的用例选择正确的误差模型至关重要。
误差效果的可视化比较
通道比较表
下表在关键特性上比较了所有七种误差通道:
| 通道 | 保持能量? | 保持相位? | CPTP? | 幺正? | 典型物理来源 |
|---|---|---|---|---|---|
| Pauli X | 否 | 是 | 是 | 是 | 自旋弛豫 |
| Pauli Y | 否 | 否 | 是 | 是 | 比特+相位翻转的组合 |
| Pauli Z | 是 | 否 | 是 | 是 | 磁通量噪声 |
| Depolarizing | 否 | 否 | 是 | 是 | 通用门误差 |
| Amplitude Damping | 否(不可逆) | 是 | 是 | 否 | T1 能量衰减 |
| Phase Damping | 是 | 否 | 是 | 是 | T2 纯退相位 |
| Decoherence | 否 | 否 | 是 | 否 | T1+T2 综合 |
如果一个通道将恒等映射到恒等,即
,则称其为幺正的(unital)。幺正通道将态驱向最大混合态 。
代码示例:比较所有误差类型
以下代码将七种误差通道分别应用于同一个 Bell 态电路,并测量输出分布相对于理想结果的变化。
from pyqpanda3 import core
import math
# Define a helper to build a Bell state circuit
def make_bell_circuit():
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])
return prog
# Error probability or rate to use for each channel
error_param = 0.05
# Map each channel name to its creation function and parameter
error_builders = {
"Pauli X": lambda: core.pauli_x_error(error_param),
"Pauli Y": lambda: core.pauli_y_error(error_param),
"Pauli Z": lambda: core.pauli_z_error(error_param),
"Depolarizing": lambda: core.depolarizing_error(error_param),
"Amp. Damping": lambda: core.amplitude_damping_error(error_param),
"Phase Damping": lambda: core.phase_damping_error(error_param),
"Decoherence": lambda: core.decoherence_error(80.0, 60.0, 20.0),
}
# Run each error model and record the Bell-state fidelity
prog = make_bell_circuit()
shots = 10000
for name, builder in error_builders.items():
noise = core.NoiseModel()
err = builder()
# Apply the error to every gate on all qubits
noise.add_all_qubit_quantum_error(err, core.GateType.CNOT)
noise.add_all_qubit_quantum_error(err, core.GateType.H)
machine = core.CPUQVM()
machine.run(prog, shots=shots, model=noise)
counts = machine.result().get_counts()
# Compute fidelity as fraction of results in {|00>, |11>}
bell = counts.get("00", 0) + counts.get("11", 0)
fidelity = bell / shots
print(f"{name:18s} fidelity={fidelity:.4f} counts={counts}")预期输出模式(由于采样,数值会有所不同):
Pauli X fidelity=0.8950 counts={'00': 4475, '11': 4475, '01': 525, '10': 525}
Pauli Y fidelity=0.8950 counts={'00': 4480, '11': 4470, '01': 520, '10': 530}
Pauli Z fidelity=0.9500 counts={'00': 4750, '11': 4750, '01': 250, '10': 250}
Depolarizing fidelity=0.8800 counts={'00': 4400, '11': 4400, '01': 600, '10': 600}
Amp. Damping fidelity=0.9200 counts={'00': 5000, '11': 4200, '01': 400, '10': 400}
Phase Damping fidelity=0.9500 counts={'00': 4750, '11': 4750, '01': 250, '10': 250}
Decoherence fidelity=0.8700 counts={'00': 4800, '11': 3900, '01': 650, '10': 650}从比较中可以得出以下关键观察:
- Pauli X 和 Y 误差产生对称的 Bell 基泄漏,在
和 中给出大致相等的布居数。 - Pauli Z 误差不改变计算基上的测量结果,因此在此特定电路上似乎保持了 Bell 保真度。然而,它们会破坏相位相干性。
- 去极化噪声在单位概率下最具破坏性,因为它同时包含所有三个 Pauli 分量。
- 振幅阻尼是不对称的:它优先将
驱向 ,因此 的计数多于 。
误差传播分析
当电路有多层门时,误差会累积。理解噪声如何随电路深度扩展对于预测算法性能至关重要。
理论背景
对于具有
其中
输出保真度(与理想态的重叠)遵循指数衰减:
其中
测量保真度与电路深度
以下实验通过运行深度递增的电路并测量输出保真度来展示噪声的累积过程。
from pyqpanda3 import core
import math
def build_layer_circuit(num_qubits, num_layers):
"""Build a circuit with repeated layers of H + CNOT gates."""
prog = core.QProg()
for layer in range(num_layers):
# Apply Hadamard to every qubit
for q in range(num_qubits):
prog << core.H(q)
# Apply CNOT between adjacent qubits
for q in range(0, num_qubits - 1, 2):
prog << core.CNOT(q, q + 1)
prog << core.measure(list(range(num_qubits)), list(range(num_qubits)))
return prog
# Set up a moderate noise model
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.depolarizing_error(0.005), core.GateType.H
)
noise.add_all_qubit_quantum_error(
core.depolarizing_error(0.02), core.GateType.CNOT
)
# Measure fidelity as a function of depth
num_qubits = 4
shots = 5000
for depth in [1, 2, 4, 8, 16, 32]:
prog = build_layer_circuit(num_qubits, depth)
# Run with noise
machine = core.CPUQVM()
machine.run(prog, shots=shots, model=noise)
noisy_counts = machine.result().get_counts()
# Run without noise for comparison
machine.run(prog, shots=shots)
ideal_counts = machine.result().get_counts()
# Compute total variation distance as a noise metric
all_keys = set(list(ideal_counts.keys()) + list(noisy_counts.keys()))
tvd = 0.0
for key in all_keys:
p_ideal = ideal_counts.get(key, 0) / shots
p_noisy = noisy_counts.get(key, 0) / shots
tvd += abs(p_ideal - p_noisy)
tvd /= 2.0
print(f"Depth={depth:3d} TVD={tvd:.4f} "
f"ideal_keys={len(ideal_counts)} noisy_keys={len(noisy_counts)}")每种门类型的误差累积
并非所有门都以相同的速率累积误差。双量子比特门的误差率通常是单量子比特门的 10-100 倍:
其中
from pyqpanda3 import core
# Demonstrate that two-qubit gate errors dominate
prog = core.QProg()
prog << core.H(0) << core.H(1) << core.H(2)
prog << core.CNOT(0, 1) << core.CNOT(1, 2)
prog << core.measure([0, 1, 2], [0, 1, 2])
# Noise only on single-qubit gates
noise_1q = core.NoiseModel()
noise_1q.add_all_qubit_quantum_error(
core.depolarizing_error(0.005), core.GateType.H
)
# Noise only on two-qubit gates
noise_2q = core.NoiseModel()
noise_2q.add_all_qubit_quantum_error(
core.depolarizing_error(0.02), core.GateType.CNOT
)
shots = 10000
machine = core.CPUQVM()
# Ideal baseline
machine.run(prog, shots=shots)
ideal = machine.result().get_counts()
# Single-qubit noise only
machine.run(prog, shots=shots, model=noise_1q)
counts_1q = machine.result().get_counts()
# Two-qubit noise only
machine.run(prog, shots=shots, model=noise_2q)
counts_2q = machine.result().get_counts()
print(f"Ideal: {ideal}")
print(f"1q noise: {counts_1q}")
print(f"2q noise: {counts_2q}")
# 2q noise will produce noticeably more deviation from the ideal distributionGateType 枚举
向噪声模型添加误差时,使用 GateType 枚举指定门类型:
# Single-qubit gates
core.GateType.H # Hadamard
core.GateType.X # Pauli-X
core.GateType.Y # Pauli-Y
core.GateType.Z # Pauli-Z
core.GateType.S # Phase gate
core.GateType.T # T gate
core.GateType.RX # RX rotation
core.GateType.RY # RY rotation
core.GateType.RZ # RZ rotation
core.GateType.U1 # U1 gate
core.GateType.U2 # U2 gate
core.GateType.U3 # U3 gate
core.GateType.U4 # U4 gate
# Two-qubit gates
core.GateType.CNOT # Controlled-NOT
core.GateType.CZ # Controlled-Z
core.GateType.CP # Controlled-Phase
core.GateType.CRX # Controlled-RX
core.GateType.CRY # Controlled-RY
core.GateType.CRZ # Controlled-RZ
core.GateType.SWAP # SWAP
core.GateType.ISWAP # iSWAP
core.GateType.SQISWAP # Square-root iSWAP
core.GateType.RXX # RXX rotation
core.GateType.RYY # RYY rotation
core.GateType.RZZ # RZZ rotation
core.GateType.RZX # RZX rotation
# Multi-qubit gates
core.GateType.TOFFOLI # Toffoli (CCNOT)运行噪声模拟
使用 CPUQVM
from pyqpanda3 import core
# Build circuit
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])
# Create noise model
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(core.depolarizing_error(0.01), core.GateType.CNOT)
noise.add_all_qubit_read_out_error([[0.95, 0.05], [0.05, 0.95]])
# Run with noise
machine = core.CPUQVM()
machine.run(prog, shots=10000, model=noise)
print(machine.result().get_counts())使用 DensityMatrixSimulator
from pyqpanda3 import core
# Build circuit (no measurement needed)
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1)
# Create noise model
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.amplitude_damping_error(0.05),
core.GateType.H
)
noise.add_all_qubit_quantum_error(
core.depolarizing_error(0.02),
core.GateType.CNOT
)
# Run with exact noise simulation
dm_sim = core.DensityMatrixSimulator()
dm_sim.run(prog, noise)
# Get noisy state probabilities
print(f"Probabilities: {dm_sim.state_probs()}")
print(f"Density matrix:\n{dm_sim.density_matrix()}")预期输出:
Probabilities: {0: 0.475, 1: 0.025, 2: 0.025, 3: 0.475}
Density matrix:
[[0.475 0. 0. 0.475]
[0. 0.025 0.025 0. ]
[0. 0.025 0.025 0. ]
[0.475 0. 0. 0.475]]使用 Stabilizer
from pyqpanda3 import core
# Clifford circuit
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])
# Noise model (only Pauli errors for Stabilizer)
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.pauli_x_error(0.01),
core.GateType.H
)
noise.add_all_qubit_quantum_error(
core.depolarizing_error(0.02),
core.GateType.CNOT
)
# Run noisy Stabilizer simulation
stab = core.Stabilizer()
stab.run(prog, shots=10000, model=noise)
print(stab.result().get_counts())实用示例
示例 1:建模真实量子设备
from pyqpanda3 import core
def create_device_noise_model():
"""Create a noise model approximating a real superconducting device."""
noise = core.NoiseModel()
# Single-qubit gate errors (higher fidelity)
single_gate_error = core.depolarizing_error(0.001)
noise.add_all_qubit_quantum_error(single_gate_error, [
core.GateType.H,
core.GateType.X,
core.GateType.Y,
core.GateType.Z,
core.GateType.S,
core.GateType.T,
])
# Two-qubit gate errors (lower fidelity)
two_gate_error = core.depolarizing_error(0.01)
noise.add_all_qubit_quantum_error(two_gate_error, [
core.GateType.CNOT,
core.GateType.CZ,
])
# T1 decay
t1_error = core.amplitude_damping_error(0.005)
noise.add_all_qubit_quantum_error(t1_error, [
core.GateType.H,
core.GateType.X,
])
# Readout errors
noise.add_all_qubit_read_out_error([
[0.97, 0.03], # P(measure 0 | true 0), P(measure 1 | true 0)
[0.04, 0.96] # P(measure 0 | true 1), P(measure 1 | true 1)
])
return noise
# Use the realistic noise model
noise = create_device_noise_model()
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1) << core.measure([0, 1], [0, 1])
machine = core.CPUQVM()
machine.run(prog, shots=10000, model=noise)
counts = machine.result().get_counts()
print(f"Device-like results: {counts}")
# With noise, will see small counts in |01⟩ and |10⟩示例 2:比较噪声水平
from pyqpanda3 import core
def run_with_noise_level(prob, shots=5000):
"""Run a Bell state with different depolarizing noise levels."""
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.depolarizing_error(prob),
core.GateType.CNOT
)
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=shots, model=noise)
return machine.result().get_counts()
# Compare noise levels
for p in [0.0, 0.01, 0.05, 0.1, 0.2]:
counts = run_with_noise_level(p)
bell_prob = (counts.get('00', 0) + counts.get('11', 0)) / 5000
print(f"p={p:.2f}: Bell fidelity ≈ {bell_prob:.3f}, counts={counts}")示例 3:逐量子比特噪声配置
from pyqpanda3 import core
# Different noise levels for different qubits
noise = core.NoiseModel()
# Qubit 0 has higher error rate
noise.add_quantum_error(
core.depolarizing_error(0.02), core.GateType.H, [0]
)
noise.add_quantum_error(
core.depolarizing_error(0.05), core.GateType.CNOT, [0, 1]
)
# Qubit 2 has lower error rate
noise.add_quantum_error(
core.depolarizing_error(0.005), core.GateType.H, [2]
)
noise.add_quantum_error(
core.depolarizing_error(0.01), core.GateType.CNOT, [2, 3]
)
# Run a 4-qubit circuit with per-qubit noise
prog = core.QProg()
prog << core.H(0) << core.H(2)
prog << core.CNOT(0, 1) << core.CNOT(2, 3)
prog << core.measure([0, 1, 2, 3], [0, 1, 2, 3])
machine = core.CPUQVM()
machine.run(prog, shots=10000, model=noise)
print(machine.result().get_counts())示例 4:噪声下的 GHZ 态
Greenberger-Horne-Zeilinger(GHZ)态
from pyqpanda3 import core
def build_ghz_circuit(num_qubits):
"""Create a GHZ state on the given number of qubits."""
prog = core.QProg()
prog << core.H(0)
for i in range(num_qubits - 1):
prog << core.CNOT(i, i + 1)
prog << core.measure(list(range(num_qubits)), list(range(num_qubits)))
return prog
# Define a realistic noise model
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.depolarizing_error(0.002), core.GateType.H
)
noise.add_all_qubit_quantum_error(
core.depolarizing_error(0.01), core.GateType.CNOT
)
noise.add_all_qubit_read_out_error([[0.97, 0.03], [0.04, 0.96]])
shots = 10000
machine = core.CPUQVM()
# Measure GHZ fidelity as a function of qubit count
for n in [2, 3, 4, 5, 6]:
prog = build_ghz_circuit(n)
machine.run(prog, shots=shots, model=noise)
counts = machine.result().get_counts()
# GHZ fidelity = fraction of results that are all-0 or all-1
all_zero = "0" * n
all_one = "1" * n
ghz_count = counts.get(all_zero, 0) + counts.get(all_one, 0)
fidelity = ghz_count / shots
print(f"n={n}: GHZ fidelity={fidelity:.4f} "
f"all-0={counts.get(all_zero,0)} "
f"all-1={counts.get(all_one,0)} "
f"total_outcomes={len(counts)}")输出将显示保真度随量子比特数迅速下降,因为 CNOT 门数量(从而累积噪声)线性增长:
n=2: GHZ fidelity=0.9750 ...
n=3: GHZ fidelity=0.9580 ...
n=4: GHZ fidelity=0.9310 ...
n=5: GHZ fidelity=0.9020 ...
n=6: GHZ fidelity=0.8640 ...示例 5:噪声扫描分析
在开发算法时,对一系列噪声参数进行扫描以确定算法失效的阈值是很有用的。本示例在变分式电路上同时扫描去极化和振幅阻尼率。
from pyqpanda3 import core
def build_variational_circuit():
"""Build a simple variational-style ansatz circuit."""
prog = core.QProg()
# Layer 1
prog << core.H(0) << core.H(1)
prog << core.CNOT(0, 1)
# Layer 2
prog << core.RZ(0, 0.5) << core.RZ(1, 0.5)
prog << core.CNOT(0, 1)
# Layer 3
prog << core.RZ(0, 0.3) << core.RZ(1, 0.3)
prog << core.H(0) << core.H(1)
prog << core.measure([0, 1], [0, 1])
return prog
def compute_hamming_distance(counts, shots):
"""Compute the average Hamming weight of measurement outcomes."""
total_weight = 0
for bitstring, count in counts.items():
weight = bitstring.count("1")
total_weight += weight * count
return total_weight / shots
prog = build_variational_circuit()
shots = 5000
machine = core.CPUQVM()
# First, get the ideal reference
machine.run(prog, shots=shots)
ideal_counts = machine.result().get_counts()
ideal_hw = compute_hamming_distance(ideal_counts, shots)
# Sweep depolarizing noise from 0.001 to 0.05
print("Depolarizing sweep:")
print(f" {'Rate':>8s} {'Hamming Weight':>15s} {'Delta from Ideal':>17s}")
for rate in [0.001, 0.005, 0.01, 0.02, 0.05]:
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.depolarizing_error(rate), core.GateType.CNOT
)
noise.add_all_qubit_quantum_error(
core.depolarizing_error(rate * 0.1), core.GateType.H
)
machine.run(prog, shots=shots, model=noise)
counts = machine.result().get_counts()
hw = compute_hamming_distance(counts, shots)
delta = abs(hw - ideal_hw)
print(f" {rate:8.4f} {hw:15.4f} {delta:17.4f}")
# Sweep amplitude damping rate from 0.001 to 0.05
print("\nAmplitude damping sweep:")
print(f" {'Rate':>8s} {'Hamming Weight':>15s} {'Delta from Ideal':>17s}")
for rate in [0.001, 0.005, 0.01, 0.02, 0.05]:
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.amplitude_damping_error(rate), core.GateType.CNOT
)
noise.add_all_qubit_quantum_error(
core.amplitude_damping_error(rate * 0.5), core.GateType.H
)
machine.run(prog, shots=shots, model=noise)
counts = machine.result().get_counts()
hw = compute_hamming_distance(counts, shots)
delta = abs(hw - ideal_hw)
print(f" {rate:8.4f} {hw:15.4f} {delta:17.4f}")请注意,振幅阻尼在 Hamming 权重中产生偏差(系统性地推向更少的 1 位),而去极化噪声产生对称的扩散。这种不对称性对于依赖精确输出分布的算法非常重要。
示例 6:噪声下的密度矩阵层析
DensityMatrix 模拟器提供精确的态信息,非常适合详细的噪声分析。本示例重建并分析 Bell 态在不同噪声通道下的密度矩阵。
from pyqpanda3 import core
import numpy as np
# Build a Bell state circuit without measurement
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1)
# Reference: ideal density matrix
dm_sim = core.DensityMatrixSimulator()
dm_sim.run(prog)
ideal_dm = dm_sim.density_matrix()
ideal_probs = dm_sim.state_probs()
print("=== Ideal Bell State ===")
print(f"Probabilities: {ideal_probs}")
print(f"Purity: {np.trace(np.dot(ideal_dm, ideal_dm)):.6f}")
# Ideal Bell state has purity = 1.0
# Analyze each noise channel's effect on the density matrix
channels = {
"Depolarizing (1%)": core.depolarizing_error(0.01),
"Amp. Damping (2%)": core.amplitude_damping_error(0.02),
"Phase Damping (2%)": core.phase_damping_error(0.02),
"Pauli X (5%)": core.pauli_x_error(0.05),
"Pauli Z (5%)": core.pauli_z_error(0.05),
}
print("\n=== Noise Channel Analysis ===")
for name, err in channels.items():
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(err, core.GateType.CNOT)
noise.add_all_qubit_quantum_error(err, core.GateType.H)
dm_sim.run(prog, noise)
noisy_dm = dm_sim.density_matrix()
noisy_probs = dm_sim.state_probs()
# Compute purity: Tr(rho^2)
purity = np.trace(np.dot(noisy_dm, noisy_dm))
# Compute fidelity with ideal state
# F(rho, sigma) = [Tr(sqrt(sqrt(rho) * sigma * sqrt(rho)))]^2
# For pure ideal state |psi>: F = <psi|rho|psi>
fidelity = np.real(ideal_dm[0, 0] * noisy_dm[0, 0]
+ ideal_dm[0, 3] * noisy_dm[3, 0]
+ ideal_dm[3, 0] * noisy_dm[0, 3]
+ ideal_dm[3, 3] * noisy_dm[3, 3])
print(f"\n{name}:")
print(f" P(00)={noisy_probs.get(0, 0):.4f} "
f"P(11)={noisy_probs.get(3, 0):.4f} "
f"P(01)={noisy_probs.get(1, 0):.4f} "
f"P(10)={noisy_probs.get(2, 0):.4f}")
print(f" Purity={purity:.4f} Bell Fidelity={fidelity:.4f}")从密度矩阵分析中可以得出以下关键要点:
- 纯度在所有噪声通道下都降至 1.0 以下,量化了噪声引入了多少混合度。
- Pauli Z 噪声降低纯度但不改变计算基概率,因为
且 。噪声仅影响非对角元素(相干项)。 - 振幅阻尼破坏了
和 之间的对称性,将概率推向 。 - 去极化噪声将概率泄漏均匀分布到所有非理想结果上。
NoiseOpType 枚举
NoiseOpType 枚举指定量子误差的内部表示:
# Kraus matrix representation
core.NoiseOpType.KARUS_MATRIICES
# Noise operation representation
core.NoiseOpType.NOISE门相关噪声
真实量子处理器对不同门类型有不同的误差率。同一设备上 Hadamard 门的误差率可能为
为什么门相关噪声很重要
逐门类型噪声配置
以下示例演示如何在单个噪声模型中为不同门类型分配不同的误差通道和误差率:
from pyqpanda3 import core
def create_gate_dependent_noise():
"""Build a noise model with distinct error profiles per gate type."""
noise = core.NoiseModel()
# Single-qubit rotation gates have low depolarizing noise
rot_error = core.depolarizing_error(0.0005)
noise.add_all_qubit_quantum_error(rot_error, [
core.GateType.H,
core.GateType.X,
core.GateType.Y,
core.GateType.Z,
core.GateType.S,
core.GateType.T,
])
# Parametric rotation gates have slightly higher noise due to
# longer gate times and calibration uncertainty
param_rot_error = core.depolarizing_error(0.001)
noise.add_all_qubit_quantum_error(param_rot_error, [
core.GateType.RX,
core.GateType.RY,
core.GateType.RZ,
])
# CNOT is the noisiest gate on superconducting hardware
cnot_error = core.depolarizing_error(0.02)
noise.add_all_qubit_quantum_error(cnot_error, core.GateType.CNOT)
# CZ gates may have different error characteristics than CNOT
cz_error = core.depolarizing_error(0.015)
noise.add_all_qubit_quantum_error(cz_error, core.GateType.CZ)
# SWAP gates are decomposed into 3 CNOTs on most hardware
swap_error = core.depolarizing_error(0.05)
noise.add_all_qubit_quantum_error(swap_error, core.GateType.SWAP)
return noise
noise = create_gate_dependent_noise()
# Build a circuit that uses multiple gate types
prog = core.QProg()
prog << core.H(0)
prog << core.RZ(1, 1.57)
prog << core.CNOT(0, 1)
prog << core.T(0)
prog << core.CZ(1, 2)
prog << core.measure([0, 1, 2], [0, 1, 2])
machine = core.CPUQVM()
machine.run(prog, shots=10000, model=noise)
print(f"Gate-dependent noise result: {machine.result().get_counts()}")每个门组合多种误差通道
在真实硬件上,单个门可能同时受到多个独立噪声源的影响。你可以通过组合误差来建模这种情况:
from pyqpanda3 import core
noise = core.NoiseModel()
# For CNOT gates, model both coherent (depolarizing) and
# incoherent (amplitude damping) noise
dep_err = core.depolarizing_error(0.015)
amp_err = core.amplitude_damping_error(0.003)
# Apply depolarizing error to CNOT
noise.add_all_qubit_quantum_error(dep_err, core.GateType.CNOT)
# Also add amplitude damping on CNOT(0, 1)
noise.add_quantum_error(amp_err, core.GateType.CNOT, [0, 1])
# For single-qubit gates, add phase damping to model T2 processes
phase_err = core.phase_damping_error(0.002)
noise.add_all_qubit_quantum_error(phase_err, [
core.GateType.H,
core.GateType.T,
core.GateType.S,
])
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1) << core.T(0)
prog << core.measure([0, 1], [0, 1])
machine = core.CPUQVM()
machine.run(prog, shots=10000, model=noise)
print(f"Multi-channel noise: {machine.result().get_counts()}")逐门噪声汇总
| 门类别 | 典型误差率 | 推荐通道 |
|---|---|---|
| Clifford 单量子比特门(H、S、X) | Depolarizing | |
| 非 Clifford 单量子比特门(T) | Depolarizing | |
| 参数化旋转门(RX、RY、RZ) | Depolarizing | |
| 双量子比特纠缠门(CNOT、CZ) | Depolarizing + Amplitude Damping | |
| SWAP(原生或分解的) | Depolarizing | |
| 测量 | 读出误差矩阵 |
噪声模型校准
为了使模拟具有预测性,需要从实际硬件表征数据推导噪声模型参数。本节介绍如何将原始校准指标转换为 pyqpanda3 的噪声模型参数。
从硬件指标到噪声参数
从 T1 推导振幅阻尼率
给定 T1 弛豫时间,对于持续时间为
对于短门时间(
from pyqpanda3 import core
import math
def t1_to_amplitude_damping(t1_us, gate_time_ns):
"""Convert T1 time and gate duration to an amplitude damping rate.
Args:
t1_us: T1 relaxation time in microseconds
gate_time_ns: gate duration in nanoseconds
Returns:
gamma: amplitude damping rate for use in amplitude_damping_error
"""
# Convert to same units (microseconds)
gate_time_us = gate_time_ns / 1000.0
gamma = 1.0 - math.exp(-gate_time_us / t1_us)
return gamma
# Example: T1 = 80 us, single-qubit gate time = 20 ns
gamma_1q = t1_to_amplitude_damping(t1_us=80, gate_time_ns=20)
print(f"1q amplitude damping rate: {gamma_1q:.6f}")
# Example: T1 = 80 us, CNOT gate time = 300 ns
gamma_2q = t1_to_amplitude_damping(t1_us=80, gate_time_ns=300)
print(f"2q amplitude damping rate: {gamma_2q:.6f}")
# Create the error channels
ad_1q = core.amplitude_damping_error(gamma_1q)
ad_2q = core.amplitude_damping_error(gamma_2q)从 T2 推导相位阻尼率
给定 T2 退相位时间,对于持续时间为
注意
from pyqpanda3 import core
import math
def t2_to_phase_damping(t2_us, gate_time_ns):
"""Convert T2 time and gate duration to a phase damping rate.
Args:
t2_us: T2 dephasing time in microseconds
gate_time_ns: gate duration in nanoseconds
Returns:
lambda_param: phase damping rate for use in phase_damping_error
"""
gate_time_us = gate_time_ns / 1000.0
lambda_param = 1.0 - math.exp(-gate_time_us / t2_us)
return lambda_param
# Example: T2 = 60 us, single-qubit gate time = 20 ns
lambda_1q = t2_to_phase_damping(t2_us=60, gate_time_ns=20)
print(f"1q phase damping rate: {lambda_1q:.6f}")
# Example: T2 = 60 us, CNOT gate time = 300 ns
lambda_2q = t2_to_phase_damping(t2_us=60, gate_time_ns=300)
print(f"2q phase damping rate: {lambda_2q:.6f}")
# Create the error channels
pd_1q = core.phase_damping_error(lambda_1q)
pd_2q = core.phase_damping_error(lambda_2q)构建校准噪声模型
以下函数演示如何从一组硬件校准参数组装完整的噪声模型:
from pyqpanda3 import core
import math
def build_calibrated_noise_model(
t1_values, # Dict[int, float]: qubit -> T1 in us
t2_values, # Dict[int, float]: qubit -> T2 in us
gate_times, # Dict[str, float]: gate name -> time in ns
rb_fidelities, # Dict[str, float]: gate name -> average gate fidelity
readout_matrix, # List[List[float]]: 2x2 assignment matrix
):
"""Build a noise model from hardware calibration data.
All parameters come from standard characterization experiments:
- T1/T2 from relaxation/echo experiments
- Gate times from hardware specifications
- RB fidelities from randomized benchmarking
- Readout matrix from measurement confusion matrices
"""
noise = core.NoiseModel()
# Convert RB fidelity to depolarizing probability.
# For a d-dimensional system, the relation is:
# F_avg = 1 - p * (d - 1) / d
# For a single qubit (d=2): p = 2 * (1 - F_avg)
for gate_name, fidelity in rb_fidelities.items():
p_dep = 2.0 * (1.0 - fidelity)
if gate_name == "H":
noise.add_all_qubit_quantum_error(
core.depolarizing_error(p_dep), core.GateType.H
)
elif gate_name == "CNOT":
noise.add_all_qubit_quantum_error(
core.depolarizing_error(p_dep), core.GateType.CNOT
)
# Add amplitude damping per qubit based on T1 and gate time
for qubit, t1 in t1_values.items():
t2 = t2_values.get(qubit, t1)
for gate_name, gt_ns in gate_times.items():
gate_time_us = gt_ns / 1000.0
gamma = 1.0 - math.exp(-gate_time_us / t1)
gate_type = core.GateType.H if gate_name == "H" else core.GateType.CNOT
qubits = [qubit] if gate_name == "H" else [0, 1]
noise.add_quantum_error(
core.amplitude_damping_error(gamma), gate_type, qubits
)
# Add phase damping based on T2
lambda_param = 1.0 - math.exp(-gate_time_us / t2)
noise.add_quantum_error(
core.phase_damping_error(lambda_param), gate_type, qubits
)
# Add readout errors from the assignment matrix
noise.add_all_qubit_read_out_error(readout_matrix)
return noise
# Example calibration data for a 2-qubit device
calibrated_noise = build_calibrated_noise_model(
t1_values={0: 80.0, 1: 65.0},
t2_values={0: 60.0, 1: 50.0},
gate_times={"H": 20.0, "CNOT": 300.0},
rb_fidelities={"H": 0.9995, "CNOT": 0.985},
readout_matrix=[[0.97, 0.03], [0.04, 0.96]],
)
# Run a test circuit with the calibrated model
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=10000, model=calibrated_noise)
print(f"Calibrated noise result: {machine.result().get_counts()}")噪声模拟工作流
噪声缓解策略
即使没有完整的量子纠错,几种实用技术也可以减少噪声对算法结果的影响。本节介绍可以在电路设计和后处理层面实施的策略。
策略概览
1. 最小化电路深度
最有效的策略是减少门的数量。每个门都是噪声进入的机会。在运行前使用编译和优化过程来降低深度。
from pyqpanda3 import core
# Inefficient: naive decomposition with many CNOT gates
prog_naive = core.QProg()
prog_naive << core.H(0)
prog_naive << core.CNOT(0, 1)
prog_naive << core.CNOT(1, 2)
prog_naive << core.CNOT(2, 3)
prog_naive << core.CNOT(3, 4)
prog_naive << core.measure([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
# Efficient: equivalent computation with fewer CNOT gates
# by reordering or exploiting circuit identities
prog_efficient = core.QProg()
prog_efficient << core.H(0)
prog_efficient << core.CNOT(0, 1)
prog_efficient << core.CNOT(0, 2)
prog_efficient << core.measure([0, 1, 2], [0, 1, 2])
# The efficient circuit has fewer two-qubit gates,
# resulting in lower accumulated noise2. 使用原生门集
在面向真实硬件时,将电路编译为设备的原生门集。使用非原生门需要分解为多个原生门,从而放大噪声。
from pyqpanda3 import core
# Some devices natively support CZ instead of CNOT.
# Using the native gate avoids decomposition overhead.
prog = core.QProg()
prog << core.H(0) << core.H(1)
prog << core.CZ(0, 1) # Use native CZ instead of decomposed CNOT
prog << core.measure([0, 1], [0, 1])
# Build a noise model that reflects the native gate's actual error rate
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.depolarizing_error(0.015), core.GateType.CZ
)
# No noise needed for CNOT since it is not used3. 读出误差缓解
可以使用校准矩阵对测量误差进行表征和校正。其思想是准备每个计算基态,多次测量,并构建分配矩阵
from pyqpanda3 import core
import numpy as np
def calibrate_readout(num_qubits, shots=10000):
"""Build a readout calibration matrix for the given qubits.
For each basis state, prepare it and measure to find
the probability of observing each outcome.
"""
dim = 2 ** num_qubits
cal_matrix = np.zeros((dim, dim))
for basis_state in range(dim):
# Prepare the basis state by applying X gates where bits are 1
prog = core.QProg()
for q in range(num_qubits):
if (basis_state >> q) & 1:
prog << core.X(q)
prog << core.measure(list(range(num_qubits)), list(range(num_qubits)))
machine = core.CPUQVM()
machine.run(prog, shots=shots)
counts = machine.result().get_counts()
# Fill the column of the calibration matrix
for outcome in range(dim):
key = format(outcome, f"0{num_qubits}b")
cal_matrix[outcome][basis_state] = counts.get(key, 0) / shots
return cal_matrix
# Calibrate a 2-qubit readout
cal_matrix = calibrate_readout(num_qubits=2, shots=10000)
print(f"Calibration matrix:\n{cal_matrix}")4. 零噪声外推
在多个人为放大的噪声水平下运行同一电路,然后外推回零噪声。这是近期设备最实用的误差缓解技术之一。
核心思想:如果噪声按
from pyqpanda3 import core
import numpy as np
def run_at_noise_scale(base_error_rate, scale_factor, shots=5000):
"""Run the benchmark circuit at an amplified noise level."""
# Amplify the error rate by the scale factor
amplified_rate = min(base_error_rate * scale_factor, 0.99)
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.depolarizing_error(amplified_rate), core.GateType.CNOT
)
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=shots, model=noise)
counts = machine.result().get_counts()
# Return the Bell-state fidelity
bell = (counts.get("00", 0) + counts.get("11", 0)) / shots
return bell
# Measure at three noise levels and extrapolate linearly
base_rate = 0.02
scales = [1.0, 2.0, 3.0]
fidelities = [run_at_noise_scale(base_rate, s) for s in scales]
# Linear extrapolation to zero noise
# Fit: f(x) = a*x + b, estimate f(0) = b
coeffs = np.polyfit(scales, fidelities, deg=1)
f_zero_noise = coeffs[1]
print(f"Noise scale factors: {scales}")
print(f"Measured fidelities: {fidelities}")
print(f"Extrapolated zero-noise fidelity: {f_zero_noise:.4f}")
# The extrapolated value should be closer to 1.0 than any individual measurement缓解策略选择指南
| 策略 | 开销 | 有效性 | 适用场景 |
|---|---|---|---|
| 最小化深度 | 无(编译时) | 中等 | 始终首先应用 |
| 原生门集 | 无(编译时) | 中等 | 面向特定硬件时 |
| 读出缓解 | 对测量密集型电路效果高 | 当读出误差占主导时 | |
| 零噪声外推 | 对中等深度电路效果高 | 通用缓解 | |
| 概率误差消除 | 随电路深度指数增长 | 效果高但代价大 | 小电路(< 20 量子比特) |
最佳实践
1. 匹配硬件噪声
使用与目标设备匹配的误差率。超导设备的典型值:
| 误差类型 | 典型率 |
|---|---|
| 单量子比特门 | |
| 双量子比特门 | |
| 读出 | |
| T1 时间 | 20-100 μs |
2. 小电路使用 DensityMatrixSimulator
对于少于约 10 个量子比特的电路,DensityMatrixSimulator 提供精确的噪声演化:
from pyqpanda3 import core
# Exact noise simulation for small circuits
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1)
noise_model = core.NoiseModel()
noise_model.add_all_qubit_quantum_error(
core.depolarizing_error(0.01), core.GateType.CNOT
)
dm_sim = core.DensityMatrixSimulator()
dm_sim.run(prog, noise_model)
exact_probs = dm_sim.state_probs()
print(f"Exact probabilities: {exact_probs}")3. 使用足够的采样次数
统计误差按
- 1000 次:约 3% 误差
- 10000 次:约 1% 误差
- 100000 次:约 0.3% 误差
4. 与理想模拟对比验证
始终将噪声结果与理想模拟进行比较,以理解噪声的影响:
from pyqpanda3 import core
# Build a Bell state circuit
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])
# Create noise model
noise = core.NoiseModel()
noise.add_all_qubit_quantum_error(
core.depolarizing_error(0.01), core.GateType.CNOT
)
machine = core.CPUQVM()
# Ideal simulation
machine.run(prog, shots=10000)
ideal_counts = machine.result().get_counts()
# Noisy simulation
machine.run(prog, shots=10000, model=noise)
noisy_counts = machine.result().get_counts()
# Compare
print(f"Ideal: {ideal_counts}")
print(f"Noisy: {noisy_counts}")