Noisy Simulation
Model real hardware imperfections by attaching a noise model to a kernel and running it on a density-matrix backend.
Selecting a noisy backend
import qalgora
qalgora.set_target("density-matrix-cpu") # tracks the full density matrix
Building a noise model
Compose channels (bit-flip, depolarization, amplitude damping) and bind them to specific gates and qubits.
noise = qalgora.NoiseModel()
# 1% depolarizing error after every Hadamard on qubit 0
noise.add_channel("h", [0], qalgora.DepolarizationChannel(0.01))
# amplitude damping + depolarizing on every `x` gate (a single-qubit channel)
# to model 2-qubit noise on CNOT / controlled-X, bind to that gate name or a
# 2-qubit channel instead (per the reference build's supported API)
noise.add_all_qubit_channel("x", qalgora.AmplitudeDampingChannel(0.02))
noise.add_all_qubit_channel("x", qalgora.DepolarizationChannel(0.02))
# apply one channel to a gate on EVERY qubit, without listing them
noise.add_all_qubit_channel("h", qalgora.DepolarizationChannel(0.005))
Running with noise
@qalgora.kernel
def bell():
q = qalgora.qvector(2)
h(q[0])
x.ctrl(q[0], q[1])
mz(q)
ideal = qalgora.sample(bell, shots_count=2000)
noisy = qalgora.sample(bell, shots_count=2000, noise_model=noise)
print("ideal:", ideal) # ~{ 00, 11 }
print("noisy:", noisy) # leaks into 01 / 10
Built-in channels
| Channel | Models |
|---|---|
BitFlipChannel(p) | X error with probability p |
PhaseFlipChannel(p) | Z error with probability p |
DepolarizationChannel(p) | Random Pauli error (X/Y/Z) with probability p |
AmplitudeDampingChannel(γ) | T1 energy relaxation toward |0⟩ |
PhaseDampingChannel(γ) | T2 dephasing without energy loss |
XError(p) / YError(p) / ZError(p) | a single Pauli error with probability p |
Pauli1(px, py, pz) | general 1-qubit Pauli channel with separate X/Y/Z rates |
Pauli2(...) | general 2-qubit Pauli channel (15 rates) |
KrausChannel([K0, K1, …]) | any channel from its Kraus operators |
Every channel is ultimately a list of KrausOperator matrices; the named channels
above are convenience constructors that build the right Kraus set for you.
Custom Kraus channel
import numpy as np
# a custom channel from its Kraus operators (must satisfy Σ Kᵢ†Kᵢ = I)
k0 = np.array([[1, 0], [0, np.sqrt(0.9)]])
k1 = np.array([[0, np.sqrt(0.1)], [0, 0]])
noise.add_channel("z", [1], qalgora.KrausChannel([k0, k1]))
Inline noise & trajectory simulation
Apply a channel at a specific point with apply_noise inside a kernel — this runs on the
reference build. For many qubits, a planned GPU trajectory backend would sample noise
stochastically as a statistical approximation, instead of tracking the full density matrix.
set_target("gpu") line is commented out so the snippet stays runnable.@qalgora.kernel
def with_inline_noise():
q = qalgora.qvector(2)
h(q[0])
qalgora.apply_noise(qalgora.DepolarizationChannel, 0.01, q[0])
mz(q)
# Planned GPU trajectory backend — not in the open reference build yet:
# qalgora.set_target("gpu") # statistical noise sampling, scales past density matrix
density-matrix-cpu is exact but must store 2ᴺ×2ᴺ complex numbers — memory grows as
4ᴺ = 2²ᴺ. Trajectory-based noise sampling (a planned GPU backend) would instead average many
stochastic runs as a statistical approximation, trading exactness for scale.
含噪声模拟
为内核附加噪声模型并在密度矩阵后端上运行,从而模拟真实硬件的缺陷。
选择含噪声后端
import qalgora
qalgora.set_target("density-matrix-cpu") # tracks the full density matrix
构建噪声模型
组合信道(比特翻转、去极化、振幅阻尼),并将其绑定到特定的门和量子比特上。
noise = qalgora.NoiseModel()
# 1% depolarizing error after every Hadamard on qubit 0
noise.add_channel("h", [0], qalgora.DepolarizationChannel(0.01))
# 对所有 x 门施加振幅阻尼与去极化(单比特信道)
# 若要模拟 CNOT/受控 X 的双比特噪声 应使用对应门名或双比特信道绑定
# (以参考实现支持的 API 为准)
noise.add_all_qubit_channel("x", qalgora.AmplitudeDampingChannel(0.02))
noise.add_all_qubit_channel("x", qalgora.DepolarizationChannel(0.02))
# 把同一信道作用到每个量子比特的该门上 无需逐一列举
noise.add_all_qubit_channel("h", qalgora.DepolarizationChannel(0.005))
带噪声运行
@qalgora.kernel
def bell():
q = qalgora.qvector(2)
h(q[0])
x.ctrl(q[0], q[1])
mz(q)
ideal = qalgora.sample(bell, shots_count=2000)
noisy = qalgora.sample(bell, shots_count=2000, noise_model=noise)
print("ideal:", ideal) # ~{ 00, 11 }
print("noisy:", noisy) # leaks into 01 / 10
内置信道
| 信道 | 模拟的噪声 |
|---|---|
BitFlipChannel(p) | 以概率 p 发生 X 错误(比特翻转) |
PhaseFlipChannel(p) | 以概率 p 发生 Z 错误(相位翻转) |
DepolarizationChannel(p) | 以概率 p 随机施加 Pauli 错误(X/Y/Z,去极化) |
AmplitudeDampingChannel(γ) | T1 能量弛豫,趋向 |0⟩(振幅阻尼) |
PhaseDampingChannel(γ) | T2 退相位,无能量损耗(相位阻尼) |
XError(p) / YError(p) / ZError(p) | 以概率 p 发生单个 Pauli 错误 |
Pauli1(px, py, pz) | X/Y/Z 速率独立的通用单比特 Pauli 信道 |
Pauli2(...) | 通用双比特 Pauli 信道(15 个速率) |
KrausChannel([K0, K1, …]) | 由 Kraus 算符定义的任意信道 |
每个信道说到底都是一组 KrausOperator 矩阵,上面这些具名信道只是帮你把对应的 Kraus 集合现成搭好的便捷构造器。
自定义 Kraus 信道
import numpy as np
# a custom channel from its Kraus operators (must satisfy Σ Kᵢ†Kᵢ = I)
k0 = np.array([[1, 0], [0, np.sqrt(0.9)]])
k1 = np.array([[0, np.sqrt(0.1)], [0, 0]])
noise.add_channel("z", [1], qalgora.KrausChannel([k0, k1]))
内联噪声与轨迹模拟
在内核中使用 apply_noise 在特定位置施加信道——这一步可在参考实现上运行。对于多量子比特场景,规划中的 GPU 轨迹后端会以随机方式采样噪声、给出统计近似,而非追踪完整密度矩阵。
set_target("gpu") 一行已注释以保证片段可运行。@qalgora.kernel
def with_inline_noise():
q = qalgora.qvector(2)
h(q[0])
qalgora.apply_noise(qalgora.DepolarizationChannel, 0.01, q[0])
mz(q)
# 规划中的 GPU 轨迹后端,开放参考实现暂未包含:
# qalgora.set_target("gpu") # 统计式噪声采样,规模可超越密度矩阵
density-matrix-cpu 结果精确,但需存储 2ᴺ×2ᴺ 个复数,内存随 4ᴺ = 2²ᴺ 增长。基于轨迹的噪声采样(规划中的 GPU 后端)则通过对大量随机运行取平均给出统计近似,以精确度换取规模。