Noise Channels
qudit.noise provides building blocks for quantum noise models: Channel holds a Kraus decomposition, Multiplex sequences multiple channels, and the Process factory constructs standard multi-qudit noise models.
Channel
A Channel represents a completely positive map in Kraus form:
Each Kraus operator Gate objects; an operator "word" that is applied left-to-right via Gate.forwardd.
| Property/Method | Description |
|---|---|
ops | List of Kraus words (list[list[Gate]]) |
d | Full Hilbert space dimension |
run(rho) | Apply |
correctable() | Return Kraus words listed in correctables |
isTP | |
isCP | Choi matrix |
isCPTP | both CP and TP? |
toChoi() | Choi–Jamiołkowski matrix |
toSuperop() | Superoperator |
toStinespring() | Stinespring isometry |
Running a channel
# Amplitude damping on 2 qubits
channel = Process.AD(d=2, n=2, Y=0.1)
# Apply to |00><00|
rho = np.zeros((4, 4), dtype=complex)
rho[0, 0] = 1.0
rho_out = channel.run(rho)
print(rho_out.shape) # (4, 4)from qudit.noise import Process
import numpy as npChannel analysis
channel = Process.AD(d=2, n=2, Y=0.1)
print(channel.isTP) # True
print(channel.isCP) # True
print(channel.isCPTP) # True
J = channel.toChoi() # shape (d^2, d^2)
S = channel.toSuperop()
V = channel.toStinespring() # isometry: V†V ≈ Ifrom qudit.noise import ProcessNOTE
isTP, isCP, isCPTP are cached_property values; they are computed once on first access and cached.
Multiplex
Multiplex sequences multiple channels, applying each in turn:
The main use case is independent identically distributed (IID) noise, where each wire gets its own channel applied sequentially.
# IID amplitude damping on 3 qubits
multi = IID.AD(n=3, y=0.05)
rho = np.zeros((8, 8), dtype=complex)
rho[0, 0] = 1.0
rho_out = multi.run(rho)from qudit.noise import IID
import numpy as npMultiplex flattens nested Multiplex inputs on construction, so Multiplex([multi1, multi2]) gives a single flat list of channels.
Process
Process constructs standard multi-qudit noise channels with correctable subsets pre-labeled.
Amplitude damping (AD)
Pure amplitude damping uses only lowering operators
channel = Process.AD(d=2, n=4, Y=0.01, order=1)| Argument | Description |
|---|---|
d | Local dimension per site (any d ≥ 2) |
n | Number of physical sites |
Y | Damping parameter |
order | Max correctable error order (default 1) |
group | If True, keep correctable sets grouped by order |
iid | If True, return Multiplex of single-wire channels |
Generalized amplitude damping (GAD)
GAD adds raising operators
channel = Process.GAD(d=2, n=4, Y=0.01, p=0.001, order=1)Same arguments as AD, plus p (environment excitation probability).
Pauli channel
px, py, pz = 0.01, 0.005, 0.01
channel = Process.Pauli(n=3, paulis=["X", "Y", "Z"], p=[px, py, pz], order=1)from qudit.noise import ProcessKraus operators are tensor products of
Depolarising channel
Applies all
channel = Process.Depolarising(d=2, n=2, p=0.05)
channel = Process.Depolarising(d=3, n=1, p=0.02) # qutritPhase damping
Kills off-diagonal coherences without energy exchange. For
channel = Process.PhaseDamp(d=2, n=2, p=0.1)Bit-flip and phase-flip channels
Qudit generalizations using the cyclic shift
channel = Process.BitFlip(d=2, n=2, p=0.05) # applies X_d with prob p
channel = Process.PhaseFlip(d=2, n=2, p=0.05) # applies Z_d with prob pBoth reduce to the standard qubit channels when d=2.
Reset channel
Collapses each qudit to
channel = Process.Reset(d=2, n=2, p=0.1)Thermal relaxation
Combined
channel = Process.ThermalRelax(n=2, T1=100e-6, T2=80e-6, t=50e-9)All Process channels accept an iid=True flag to return a Multiplex of independent single-site channels instead of a joint
Weyl-Heisenberg channel (NoisyGate)
For circuit-level noise in Mode.NOISY, NoisyGate("weyl", param, ...) implements the Heisenberg-Weyl displacement channel for any local dimension
where param is a length-
from qudit.circuit.gates import NoisyGate
import torch
# Qubit Weyl (d=2): 3 parameters for W_01=Z, W_10=X, W_11=XZ
ng2 = NoisyGate("weyl", torch.tensor([0.02, 0.01, 0.01]), index=0, wires=1, dims=2)
# Qutrit Weyl (d=3): 8 parameters for all (m,n) ≠ (0,0)
ng3 = NoisyGate("weyl", torch.tensor([0.005]*8), index=0, wires=1, dims=3)Correctable subsets
After building a channel, channel.correctables holds a flat list (or grouped list if group=True) of Kraus-word indices that are considered correctable up to the given order.
channel = Process.GAD(2, 4, Y=0.01, p=0.001)
Ek = channel.correctable() # list of Kraus operator listsThese are passed directly to Recovery.leung for constructing recovery maps (see Error Correction).
IID noise
IID builds single-wire channels and multiplexes them for independent identically distributed noise. Both factories work for any local dimension d ≥ 2:
| Factory | Signature | Description |
|---|---|---|
IID.AD | (n, d, y) | Amplitude damping on each of n qudits independently |
IID.GAD | (n, d, y, p) | Generalized amplitude damping on each qudit independently |
IID.Depolarising | (n, d, p) | Depolarising channel on each qudit independently |
IID.PhaseDamp | (n, d, p) | Phase damping on each qudit independently |
IID.BitFlip | (n, d, p) | Bit-flip ( |
IID.PhaseFlip | (n, d, p) | Phase-flip ( |
IID.Reset | (n, d, p) | Reset to $ |
qubit = IID.AD(n=3, d=2, y=0.05)
qutrit = IID.AD(n=2, d=3, y=0.1)from qudit.noise import IIDTIP
Use Process.AD(d=..., n=..., iid=True) as a shortcut; it delegates to IID.AD and returns a Multiplex.